No description
Find a file
zemdregon 9cea1c8d9b
Some checks are pending
CI / validate (push) Waiting to run
chore: pin media-automation to v0.1.8
Match published release used by the host MVP binary after offline Dispatch/ImportPath cut.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 18:07:20 -05:00
.github/workflows fix(ci): self-hosted runners and drop go test -race 2026-08-10 10:49:18 -05:00
scripts Fix validate main() wiring for catalog pin cross-check. (#48) 2026-08-10 00:43:13 -05:00
tags chore: pin media-automation to v0.1.8 2026-08-10 18:07:20 -05:00
.gitignore Official MuxCore module spool 2026-06-14 08:48:08 -05:00
catalog.json chore: pin media-automation to v0.1.8 2026-08-10 18:07:20 -05:00
LICENSE Official MuxCore module spool 2026-06-14 08:48:08 -05:00
README.md chore: default to cache-local; optional cache-redis tag (2.4.77). 2026-08-10 10:42:11 -05:00
SECURITY.md feat: add acquisition tag pack and refresh catalog docs 2026-07-22 19:10:04 -05:00

MuxCore Official Spool

This is the official module spool for MuxCore. Add this repository URL to your MuxCore instance to discover official modules and tags.

URL

https://github.com/Muxcore-Media/spool

Tags

Tags are curated module presets — a named set of modules that work together. Pull a tag to load its modules:

# Start MuxCore with the default tag from the official spool
muxcored --tag default

# Use a minimal preset
muxcored --tag minimal

# Media libraries + scanner / roots (fixture-friendly)
muxcored --tag media

# Fixture-first library ingest (no live indexer)
muxcored --tag acquisition

# Optional music/books (+ comics/audiobooks) libraries — not in default/media
muxcored --tag library-plus

Available Tags

Tag Description
default Admin UI, REST API, local auth, SQLite, cache-local, call/publish policy defaults, encryption, secrets, health monitoring, rate limiting, cron scheduler, tapestry workflow
minimal Bare essentials: admin UI, REST API, local auth, SQLite, encryption, secrets, health monitoring
media TMDB metadata, movie/TV libraries, automation, call/publish policies, scanner, roots, Jellyfin
acquisition Fixture-first ingest: scanner, root folders, optional list sync — no Pirate Bay / Torznab pin
library-plus Optional: media-music + media-books (required), media-comics + media-audiobooks (optional) — not part of default/media
workflow Optional: workflow-tapestry DAG engine — also listed optional on default; opt in with --tag workflow
cache-redis Optional: swap to cache-redis (shared Redis) — not default; do not combine with cache-local
secrets-vault Optional: swap to secrets-vault (Vault/OpenBao / cloud mocks for CI) — not default; do not combine with secrets-file

Every module entry in a tag pins an explicit published semver (vX.Y.Z) that must match catalog.json. Floating latest is rejected by validation.

worker-pool-memory remains in catalog.json but is deprecated (prefer cores built-in worker pool).

Fixture-first acquisition

Laptop demos and product gates use fixture / offline acquisition — not live pirate indexers or BitTorrent swarms.

  • acquisition pins only library ingest helpers (media-scanner, media-root-folders, optional media-list-sync). It does not require indexer-piratebay, Torznab, or a live downloader.
  • media adds libraries, automation, and metadata. It also omits live indexer defaults.
  • Pair either tag with the installer / _mvp default DOWNLOADER_ENGINE=fixture when you need a completed download without a swarm.
  • Leave PIRATEBAY_API_BASE / Torznab URLs unset. Operators who want live indexers must opt in outside these presets (and keep that path out of CI/smoke gates).
export DOWNLOADER_ENGINE=fixture   # installer / _mvp default
muxcored --tag acquisition         # ingest helpers only
# or:
muxcored --tag media               # libraries + automation, still no live indexer pin

Optional library-plus

Music, books, comics, and audiobook managers stay out of default / media so laptop movie/TV demos stay lean. Pull them explicitly:

muxcored --tag library-plus
Module Pin Role in tag
media-music v0.1.0 (catalog) required
media-books v0.1.0 (catalog) required
media-comics v0.1.0 (catalog) optional (required: false)
media-audiobooks v0.1.0 (catalog) optional (required: false)

Pins are the published catalog semver tags. For MuxCore monorepo / workspace demos, you may load the sibling checkouts under media-music/, media-books/, media-comics/, and media-audiobooks/ at those same versions instead of fetching GitHub release artifacts — keep pin strings aligned with catalog.json so scripts/validate.py stays green.

Optional workflow

muxcored --tag workflow

Loads workflow-tapestry (v0.1.6). Also present as required: false on the default tag.

Optional cache-redis

Default keeps cache-local. For multi-host / durable shared cache:

muxcored --tag cache-redis

Do not combine with cache-local in the same mesh. CI in the cache-redis repo uses miniredis for unit tests and optional redis:7-alpine for a live round-trip.

Optional secrets-vault

Default / minimal keep secrets-file. Swap to Vault/OpenBao (or other backends) with:

muxcored --tag secrets-vault

Do not combine with secrets-file in the same mesh. Local OpenBao Docker smoke lives in the secrets-vault repo (deploy/run-openbao-smoke.sh).

Schema validation

scripts/validate.py checks catalog.json and tags/*.json (required fields, unique repos, semver pins matching the catalog, and no live indexer peers in curated tags). CI runs it on self-hosted runners:

SKIP_REMOTE=1 python3 scripts/validate.py

Omit SKIP_REMOTE (or leave it unset) to also warn when catalog pins are missing as GitHub release tags.

Secrets backends

Preset tags (default, minimal) pin secrets-file for local encrypted-file secrets. Optional tag secrets-vault pins secrets-vault (v0.1.1) for Vault/OpenBao (local Docker smoke), Infisical, AWS Secrets Manager, GCP Secret Manager, or Azure Key Vault. Not part of default/minimal — opt in with --tag secrets-vault. Never run both secrets modules (one secrets capability per mesh). secrets-vault does not embed a secrets server; point env at OpenBao/Vault or your provider (cloud backends are mock-only in unit tests).

Cache backends

Preset tags default (and laptop demos) pin cache-local (v0.1.1) for a process-local in-memory CacheLayer (cache.local, plus legacy cache.memory alias). Optional tag cache-redis pins cache-redis (v0.1.5) when you need a shared Redis. Not part of default/minimal — opt in with --tag cache-redis. Never run both cache modules (one cache capability per mesh).

muxcored --tag cache-redis

Tag Definition Format

Tags live in tags/<name>.json:

{
  "name": "default",
  "description": "The official MuxCore starter setup",
  "version": "2.1.0",
  "modules": [
    {
      "repo": "https://github.com/Muxcore-Media/admin-ui",
      "version": "v0.1.0",
      "required": true
    }
  ]
}
  • required: true — core refuses to start without this module
  • required: false — core starts without it but logs a warning

For Third-Party Spools

Anyone can create a spool. Create a repo with a catalog.json and tags/ directory. Users add your repo URL to their MuxCore instance with --spool <url>.

Security Warning

Third-party spools are untrusted. Modules run with the same privileges as the core process. See SECURITY.md for the full security disclaimer.

Module Repo Requirements

Each module repo must have a muxcore.json at its root with:

{
  "name": "Module Name",
  "description": "What it does",
  "version": "1.0.0",
  "icon": "https://...",
  "author": "Author Name",
  "kind": "example",
  "capabilities": ["example.capability"],
  "dependencies": [],
  "homepage": "https://github.com/org/repo"
}

Contract Declarations (Required for Third-Party Modules)

If your module uses contract repos that are not from the Muxcore-Media GitHub organization, declare them in muxcore.json under contracts:

{
  "name": "My Custom Module",
  "kind": "example",
  "capabilities": ["example.custom"],
  "contracts": [
    {
      "repo": "github.com/my-org/contracts-example",
      "version": "v2.0.0",
      "interface": "Example"
    }
  ]
}

How Contract Reconciliation Works

MuxCore uses Go's nominal type system for compile-time safety. Two interfaces with identical method sets but different package paths (e.g., github.com/my-org/contracts-example.Downloader vs github.com/Muxcore-Media/contracts-example.Example) are different types in Go.

When MuxCore tooling reconciles a module with non-canonical contracts:

  1. The reconciler (contracts-reconciler) fetches both the third-party contract repo and the canonical Muxcore-Media equivalent
  2. It parses both Go source files and extracts interface method signatures via AST
  3. If the method sets are structurally identical, it generates a go.mod replace directive that normalizes the import to the canonical path
  4. If they differ, the import is rejected with a detailed mismatch report

This preserves compile-time type safety while keeping the MuxCore philosophy: contracts are patterns, not org-bound dependencies.

Requirements for Contract Repos

Third-party contract repos must define interfaces with structurally identical method signatures to the canonical equivalents. Only method names, parameter types, and return types are compared — package paths, comments, and embedded interfaces are ignored.

Recommended: Use Go type aliases to avoid reconciliation entirely:

package example

import "github.com/Muxcore-Media/contracts-example"

// This IS the same type — no reconciliation needed
type Example = contracts_example.Example

Modules that use type aliases don't need contract declarations — the Go compiler already sees them as the canonical types.