# Contract: m2/market-registry repo layout + PR/veto protocol (v1, frozen) Registry of record on Forgejo (`git.machinemachine.ai/m2/market-registry`). Truth for listings and audit; everything downstream (catalog, store, CLI) is derived and rebuildable. ## Layout ``` listings// ├── listing.json # conforms to schemas/listing.schema.json ├── solution.json # conforms to schemas/solution.schema.json (current version) └── evidence/ # provenance files referenced by solution.evidence[] audit/ └── YYYY-MM-DD.json # daily ledger balance snapshots (ledger-api /snapshot) schemas/ -> mirrored copy of frozen v1 schemas (CI validates listings against them) ``` Solution bundles (tarballs: `solution.json` + `payload/` + `recipe.yaml`) attach as **repo releases** tagged `-v`; `listing.json.install_ref` names the tag. ## Publish protocol (Story 2) 1. Builder branch `listing/` adds/updates `listings//`. 2. PR opened with template: evidence summary, price, permissions diff, rollback note. Status: `in_review`. 3. CI validation on PR (schema-validate, evidence non-empty, tenant-firewall rules, content_hash matches release asset) — hard-fails before human review (FR-015, spec Story 2 AC-2). 4. Human review window; label `veto` → close (back to draft). Label `approved` + merge → `published`. (Same veto semantics the fedlearn pipeline uses; when fedlearn's curation `commercialize` disposition lands, it opens THIS PR shape — that is the integration seam.) 5. Merge webhook (or indexer poll) triggers catalog index (contracts/catalog-index.md). ## Delist protocol Commit setting `listing.json.status = "delisted"` (PR, lighter review). Licenses and installed bundles remain valid; catalog entry removed on next index; release assets kept. ## Rules - No secrets anywhere in the repo (constitution VI); evidence is scrubbed before commit. - Registry wins over index on divergence; `m2-market-indexer reindex` rebuilds the partition from `main` (constitution II). - Tenant-derived listings require `owner_initiated` + double-scrub attestations in the PR body; CI rejects `tenant_scope` violations mechanically.