gabriel / musehub public
mist-domain.md markdown
427 lines 13.0 KB
Raw
sha256:3c58668648c7323bb9f5c6881cfe6a3f14fc93fcb73b537d253732952a5bf8bf chore: bump version to 0.2.0rc12 Sonnet 4.6 patch 9 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 1 commit
sha256:35d76015db2541686c33edd44343ea2d9f751325b4a5556cc9c4c9c0f84edbbe chore: bump version to 0.2.0rc12 Sonnet 4.6 patch 7 days ago