gabriel / musehub public
mist-domain.md markdown
427 lines 13.0 KB
Raw
sha256:34035d72cef530c1ab9d6a6f53be18d803dde705fc3157617d70352a96d0747b Merge branch 'fix/wire-push-external-parent-manifest' into dev Human 8 days ago

Mist Domain — Complete Reference

Last updated: 2026-04-15

A Mist is a content-addressed, cryptographically signable, forkable, embeddable artifact share. It is the sixth interface of the Muse universe — what a gist becomes when you reimagine it through the full Muse philosophy.


Contents

  1. Concepts
  2. URL Schema
  3. Artifact Types
  4. CLI Reference
  5. REST API
  6. MCP Tools & Resources
  7. Agent Publishing Workflow
  8. Forking & Sub-domain Delegation
  9. Embedding
  10. Content Addressing
  11. Security Model
  12. Limits

Concepts

Property Value
Identity Content-addressed — SHA-256 over content bytes, base-58 encoded, truncated to 12 chars
Storage Every mist is a Muse repo with domain="mist"
Versioning Full muse log, muse diff, muse checkout on the backing repo
Authorship Optional Ed25519 (--sign) or GPG signature proving human/agent identity
Visibility public (default) or secret
Forkability Any public mist is forkable; fork depth capped at 5
Embeddability Standalone iframe card served at /{owner}/mists/{id}/embed

URL Schema

# Web UI
https://musehub.ai/{owner}/mists/{mist_id}           # detail page
https://musehub.ai/{owner}/mists/{mist_id}/embed     # iframe-safe embed card
https://musehub.ai/{owner}/mists/{mist_id}/raw       # raw artifact download
https://musehub.ai/{owner}/mists                     # owner's public mist list
https://musehub.ai/mists/explore                     # global discovery feed

# REST API
POST   /api/mists                                    # create
GET    /api/mists/{mist_id}                          # read
PATCH  /api/mists/{mist_id}                          # update (owner only)
DELETE /api/mists/{mist_id}                          # delete (owner only)
POST   /api/mists/{mist_id}/fork                     # fork
GET    /api/mists/{mist_id}/forks                    # list direct forks
GET    /api/mists/explore                            # global public feed
GET    /api/{owner}/mists                            # owner's public list
GET    /api/{owner}/mists/{mist_id}/embed            # embed codes

# MCP Resource
musehub://mists/{owner}/{mist_id}                    # single mist resource
musehub://mists/{owner}                              # owner's mist list resource

Artifact Types

The server auto-detects the artifact type from the filename and content bytes. Callers may omit artifact_type in POST /api/mists — the server fills it in.

Type Detection heuristic Language detection
code Common code extensions (.py, .js, .ts, .rs, .go, …) Yes — extracted from extension
midi .mid / .midi extension or MIDI magic bytes (4D 54 68 64) No
schema .json + JSON content with $schema or type/properties keys No
abi .abi, .abi.json, or JSON array of ABI objects No
dataset .csv, .tsv, .ndjson, .jsonl No
config .yaml, .yml, .toml, .env, .ini, .conf No
text .md, .txt, .rst, .adoc or unrecognised text No
unknown Binary content with no recognised signature No

Symbol anchors (symbol_anchors) are extracted automatically for Python, JavaScript, and TypeScript code artifacts. They appear in the sidebar on the detail page and in the MCP resource response.


CLI Reference

The muse mist subcommand is the primary interface for humans and agents.

Create

muse mist create <file> [options]

Options:
  --title TEXT          Human-readable title
  --description TEXT    Longer description (shown on the detail page)
  --visibility          public (default) | secret
  --tags TAG,...        Comma-separated tags (max 10, 64 chars each)
  --agent-id TEXT       Agent identifier for provenance (e.g. "cccode-v3")
  --model-id TEXT       Model ID for agent provenance (e.g. "claude-sonnet-4-6")
  --sign                Sign with the local Ed25519 identity key (~/.muse/identity.toml)
  --push                Push to the configured hub after creation
  --json                Machine-readable output

Example:

muse mist create validate_handle.py \
  --title "Handle validation primitive" \
  --tags "security,auth" \
  --sign --push --json
# → {"mist_id": "aB3xKq9dPwNm", "url": "https://musehub.ai/gabriel/mists/aB3xKq9dPwNm", ...}

List

muse mist list [--owner HANDLE] [--artifact-type TYPE] [--limit N] [--json]

Read

muse mist read <mist_id> [--json]

Fork

muse mist fork <mist_id> [--push] [--json]

Update

muse mist update <mist_id> [--title TEXT] [--description TEXT]
                           [--visibility public|secret] [--content FILE]
                           [--tags TAG,...] [--json]

Delete

muse mist delete <mist_id> [--json]

REST API

All write endpoints require Authorization: MSign ... (see MSign reference).

POST /api/mists

Create a new mist. The mist_id is computed by the server — callers do not supply it.

Request body:

{
  "filename":    "validate_handle.py",
  "content":     "def _validate_handle(h): ...",
  "visibility":  "public",
  "title":       "Handle validation primitive",
  "description": "Security gate used by auth middleware.",
  "tags":        ["security", "auth"],
  "agentId":     "cccode-v3",
  "modelId":     "claude-sonnet-4-6",
  "gpgSignature": ""
}

Response (201):

{
  "mistId":       "aB3xKq9dPwNm",
  "url":          "https://musehub.ai/gabriel/mists/aB3xKq9dPwNm",
  "owner":        "gabriel",
  "filename":     "validate_handle.py",
  "artifactType": "code",
  "language":     "python",
  "content":      "def _validate_handle(h): ...",
  "sizeBytes":    42,
  "version":      1,
  "visibility":   "public",
  "title":        "Handle validation primitive",
  "description":  "Security gate used by auth middleware.",
  "tags":         ["security", "auth"],
  "agentId":      "cccode-v3",
  "modelId":      "claude-sonnet-4-6",
  "signed":       false,
  "forkCount":    0,
  "viewCount":    0,
  "embedCount":   0,
  "forkDepth":    0,
  "forkParentId": null,
  "symbolAnchors": ["validate_handle.py::_validate_handle"],
  "createdAt":    "2026-04-15T12:00:00+00:00",
  "updatedAt":    "2026-04-15T12:00:00+00:00"
}

409 Conflict — Same content already exists under your handle (idempotent: the existing mist_id is stable).

PATCH /api/mists/{mist_id}

Partial update. Only provided fields change; omit a field to leave it unchanged.

{
  "title":       "New title",
  "visibility":  "secret",
  "content":     "def _validate_handle(h): pass  # v2",
  "tags":        ["security", "auth", "v2"]
}

Updating content increments version and records a new commit on the backing repo.

404 if mist_id not found or caller is not the owner.

DELETE /api/mists/{mist_id}

Hard delete. 204 on success. 404 if not found or not the owner.

POST /api/mists/{mist_id}/fork

Create a fork. The fork gets a new mist_id (computed from the content + caller identity + timestamp) and fork_depth = parent.fork_depth + 1.

422 if the parent is already at depth 5.

GET /api/mists/explore

Global public discovery feed. Supports artifact_type and cursor pagination.

GET /api/mists/explore?artifact_type=code&limit=20&cursor=<ISO-8601>

Response shape:

{
  "mists":      [...],
  "total":      1234,
  "nextCursor": "2026-04-14T09:30:00+00:00"
}

MCP Tools & Resources

Tools

Tool Auth Description
muse_mist_create write Create a new mist
muse_mist_update write Patch title/description/visibility/tags/content
muse_mist_fork write Fork a public mist
muse_mist_delete write Hard-delete a mist (owner only)
muse_mist_read read Fetch full mist including content
muse_mist_list read List mists (owner or global explore)
muse_mist_embed read Get iframe, script, and badge embed codes

Resources

musehub://mists/{owner}/{mist_id}   — full mist response (content included)
musehub://mists/{owner}             — owner's public mist list (no content)

Secret mists are returned for the authenticated owner; unauthenticated or non-owner reads of secret mists return a forbidden error.


Agent Publishing Workflow

An agent session produces an artifact it wants to share permanently:

# Via MCP tool (no shell required):
result = muse_mist_create(
    filename="validate_handle.py",
    content=content,
    title="Handle validation security primitive",
    agent_id="cccode-v3",
    model_id="claude-sonnet-4-6",
    visibility="public",
    tags=["security", "auth"],
)
# → {"mistId": "aB3xKq9dPwNm", "url": "https://musehub.ai/gabriel/mists/aB3xKq9dPwNm", ...}

Or via CLI (signed with MUSE_AGENT_KEY env var injected by Agentception):

muse mist create /tmp/validate_handle.py \
  --title "Handle validation security primitive" \
  --agent-id cccode-v3 \
  --model-id claude-sonnet-4-6 \
  --sign --push --json

The resulting URL is a permanent, verifiable artifact:

  • The human can view it at https://musehub.ai/{owner}/mists/{id}
  • It can be forked, improved, and a proposal submitted back to the original
  • It can be embedded in blog posts via <iframe> or <script>
  • The agent_id and model_id fields are displayed on the detail page, proving provenance
  • In the ERC8004 on-chain identity world: agent contract address → MSign key → Mist signature → content hash

Forking & Sub-domain Delegation

Every mist is a Muse repo (domain="mist"). Forking creates a new repo whose first commit copies the parent's content. The fork graph is visible on the detail page sidebar (Forked From + Forks panels).

Depth limit: Fork chains are capped at depth 5. This prevents infinite fork-bomb chains that could exhaust storage. The server returns 422 when a depth-5 mist is forked.

Sub-domain delegation (future): Because each mist backs a full Muse repo, any future domain plugin (genomics, spatial, MIDI v2) can be applied to the backing repo. A mist that was created as artifact_type=code can have its repo re-initialised under a code domain plugin and gain symbol-level diffs, blast radius, and AST versioning for free.


Embedding

iframe

<iframe
  src="https://musehub.ai/{owner}/mists/{mist_id}/embed"
  width="600"
  height="400"
  frameborder="0"
  title="my_file.py">
</iframe>

The embed card shows the artifact type chip, filename, content (Prism.js syntax-highlighted), size/version metadata, and a "View on MuseHub" link.

Script tag

<script
  src="https://musehub.ai/embed.js"
  data-mist="{owner}/{mist_id}">
</script>

The embed endpoint increments embed_count on each render. Cross-origin framing is allowed (frame-ancestors *).


Content Addressing

The mist_id is computed deterministically from the artifact bytes:

import hashlib, base58

def compute_mist_id(content: bytes) -> str:
    digest = hashlib.sha256(content).digest()
    return base58.b58encode(digest).decode()[:12]

Properties:

  • Deterministic: The same file always produces the same mist_id.
  • Collision-resistant: SHA-256 with 12-char base-58 → ~7×10¹⁶ distinct IDs.
  • Offline verifiable: Any caller can recompute the ID and confirm integrity without contacting the server.
  • Idempotent creates: POST /api/mists with the same content returns 409 (the existing mist is not overwritten).

Security Model

Threat Mitigation
Path traversal via filename _validate_mist_filename() in muse/plugins/mist/plugin.py rejects .., /, \, null bytes, control chars, ANSI escapes
Content injection (XSS) Content stored verbatim; Jinja2 auto-escapes {{ mist.content \| e }} at render time
Oversized content ContentSizeLimitMiddleware returns 413 for bodies > 10 MiB
Unauthorised mutation PATCH/DELETE check mist.owner == caller.handle; return 404 on mismatch
Secret mist leakage Secret mists excluded from /explore and owner list; direct GET returns 403
Fork bomb Depth cap enforced at service layer (_FORK_DEPTH_LIMIT = 5) and REST route (422)
Rate limiting MIST_CREATE_LIMIT = 20/min, MIST_FORK_LIMIT = 30/min per MSign handle
Tag injection validate_tags() enforces count ≤ 10, length ≤ 64, no null bytes

Limits

Parameter Limit
Content size 10 MiB (enforced by middleware)
Filename length 255 characters
Title length 500 characters
Description length 10,000 characters
Tag count 10
Tag length 64 characters
Fork depth 5
Create rate 20 / minute per handle
Fork rate 30 / minute per handle
Explore page size 1–100 (default 20)
File History 14 commits
sha256:34035d72cef530c1ab9d6a6f53be18d803dde705fc3157617d70352a96d0747b Merge branch 'fix/wire-push-external-parent-manifest' into dev Human 8 days ago
sha256:fc04e4cae9e1774d6a21b65c45daeed0e6787eb581d13aa1b03bfe9384a34226 Merge branch 'fix/two-column-scroll-layout' into dev Human 8 days ago
sha256:408916fc5973ba59c6e4eebaa80ebdcc801c0a63205651e25009d11548f79454 chore: bump version to 0.2.0.dev2 — nightly.2, matching muse Sonnet 4.6 patch 11 days ago
sha256:d035733f21ccff27735fddebfbbe0ed24565a32a22db8de5885402262671ecd2 chore: bump version to 0.2.0rc15 for musehub#113 fix release Sonnet 4.6 patch 14 days ago
sha256:0032d6cfa33bc3c8367436ad768e7dd0e339b4332153160247da8266cb5fa352 Merge branch 'task/version-tags-phase3-server' into dev Human 17 days ago
sha256:4669620efda9ff41c55bdefd1f7bfe1c239d468428744c84ead9957e5a003a53 merge: rescue snapshot-recovery hardening (c00aa21d) into d… Opus 4.8 minor 29 days ago
sha256:a59da49c4611b970fc4b6ae48678ce4943261c213a07ddbd73ce9201df869b4a fix: remove false-positive proposal_comments index drop fro… Sonnet 4.6 patch 33 days ago
sha256:0a240d6dbff234f07d98a28a4a9a68db702f3f9ff9260196f24219bdb1c0b6f3 feat: render markdown mists as HTML with heading anchor links Sonnet 4.6 patch 34 days ago
sha256:24a7d47486ebc4ebd1832830580e177ec6f877b48dced8c000e198cdec4ce9d6 Merge 'task/bump-version-rc12' into 'dev' — proposal: Bump … Human 35 days ago
sha256:b9ff931d147e0114a1f17060f415b89ed551c170a91ff226c70437aa5c85f9ee Merge 'task/bump-version-rc12' into 'dev' — proposal: Bump … Human 35 days ago
sha256:d1122d21e73471879b460037b22c0b50fded7c423444a176f248428f75dac39c Merge 'task/fix-issue-pagination-cursor' into 'dev' — propo… Human 35 days ago
sha256:01e18975e73d2b3cd5b6db7929c895bef9aa6e0d4391dc5b2adfc548b41318dd Merge 'feat/adding-debug-logs-to-staging' into 'dev' — prop… Human 35 days ago
sha256:6b1949fc2797ca4c1936a637a4cbfec828ef56cf52398a2e74ca3c4f494e728f fix: use wire_bytes not mpack_bytes_raw in compute_object_b… Sonnet 4.6 patch 48 days ago
sha256:b99f2455dc346966d040133f5203297e6e3ef5803a93728a2c30568d0a0f7583 rename: delta_add → delta_upsert across wire format, models… Sonnet 4.6 patch 50 days ago