{
  "schema": "ecorce.surface.catalogue/1.0",
  "kernel_version": "manifest@v1",
  "name": "Écorce — surface réseau (démo)",
  "tagline": "Écorce, ton moteur de connexion",
  "method": "GET-only",
  "status": "demo",
  "rule": "Lists only capabilities that actually work right now. If a capability is not here, it does not exist.",
  "test_data": true,
  "test_label": "données d'exemple — inventées / invented example data",
  "endpoints": {
    "mcp_anonymous": "https://ecorce.app/mcp",
    "mcp_member": "https://ecorce.app/member/mcp",
    "manifests": "https://ecorce.app/api/manifests",
    "invoke": "https://ecorce.app/api/invoke",
    "compose": "https://ecorce.app/api/compose",
    "oauth_metadata": "https://ecorce.app/.well-known/oauth-authorization-server",
    "openapi": "https://ecorce.app/openapi.json",
    "docs": "https://ecorce.app/docs",
    "llms": "https://ecorce.app/llms.txt",
    "opportunities": "https://ecorce.app/api/opportunities",
    "shared_tools": "https://ecorce.app/api/shared-tools",
    "wfp_functions": "https://ecorce.app/api/functions"
  },
  "access_model": {
    "mode": "Read-Open / Write-Gated",
    "public_read_and_simulation": "100% open for free without key (simulated: true, persisted: false)",
    "persistent_write": "Requires partner invite code via X-Ecorce-Invite header, Authorization: Bearer <invite_code>, or JSON invite_code field",
    "request_invite": "equipe@ecorce.app"
  },
  "mandates": {
    "anonymous": {
      "id": "mandate-demo-draft-only",
      "type": "mandate",
      "principal": "anonymous visitor",
      "scopes": [
        "read:catalogue",
        "create:order_draft",
        "read:order_draft"
      ],
      "denied": [
        "confirm:order_draft",
        "place:order",
        "pay"
      ],
      "limits": [],
      "expires": null,
      "summary_fr": "Mandat anonyme de démonstration: l'agent peut lire et rédiger des brouillons. Il ne peut ni confirmer, ni passer, ni payer une commande.",
      "summary_en": "Anonymous demo mandate: the agent may read and draft. It may never confirm, place or pay for an order."
    },
    "member": "per member, per-partner limits in CAD; read with get_mandate on /member/mcp"
  },
  "system_manifests": [
    {
      "id": "ecorce:spn-catalogue@v1",
      "protocol": "ecorce.catalog_search@v1",
      "function_ref": "fn-ecorce-spn-catalogue",
      "human_approval_on_commit": false
    },
    {
      "id": "ecorce:unit-economics-advisor@v1",
      "protocol": "ecorce.margin_and_logistics_advisor@v1",
      "function_ref": "fn-ecorce-unit-economics",
      "human_approval_on_commit": false
    },
    {
      "id": "ecorce:order-draft-engine@v1",
      "protocol": "ecorce.order_draft@v1",
      "function_ref": "fn-ecorce-order-draft",
      "human_approval_on_commit": true
    },
    {
      "id": "saja:tournee-pool-g9a@v1",
      "protocol": "ecorce.route_pool@v1",
      "function_ref": "fn-saja-tournee-g9a",
      "human_approval_on_commit": true
    },
    {
      "id": "lamoisson:besoins-hebdo@v1",
      "protocol": "ecorce.restock_needs@v1",
      "function_ref": "fn-lamoisson-besoins",
      "human_approval_on_commit": true
    },
    {
      "id": "ecorce:fruits-legumes-hebdo@v1",
      "protocol": "ecorce.weekly_produce_pool@v1",
      "function_ref": "fn-ecorce-fruits-legumes",
      "human_approval_on_commit": true
    }
  ],
  "capabilities": [
    {
      "id": "manifests.publish",
      "kind": "buildable",
      "works": true,
      "mcp_tool": "publish_manifest",
      "rest": "POST /api/manifests"
    },
    {
      "id": "shared_page.publish",
      "kind": "buildable",
      "works": true,
      "mcp_tool": "publish_shared_page",
      "rest": "POST /api/manifests",
      "ui": "https://ecorce.app/p/{actor}/{slug}"
    },
    {
      "id": "manifests.list",
      "kind": "discoverable",
      "works": true,
      "mcp_tool": "list_manifests",
      "rest": "GET /api/manifests"
    },
    {
      "id": "manifests.get",
      "kind": "discoverable",
      "works": true,
      "rest": "GET /api/manifests/{id}"
    },
    {
      "id": "manifests.invoke",
      "kind": "transactional",
      "works": true,
      "mcp_tool": "invoke_manifest",
      "rest": "POST /api/invoke"
    },
    {
      "id": "manifests.compose",
      "kind": "transactional",
      "works": true,
      "mcp_tool": "compose_manifests",
      "rest": "POST /api/compose"
    },
    {
      "id": "partners.list",
      "kind": "discoverable",
      "works": true,
      "mcp_tool": "list_partners",
      "rest": "GET /api/partners"
    },
    {
      "id": "catalogue.search",
      "kind": "discoverable",
      "works": true,
      "mcp_tool": "search_catalogue",
      "rest": "GET /api/catalogue",
      "manifest_id": "ecorce:spn-catalogue@v1",
      "function_ref": "fn-ecorce-spn-catalogue"
    },
    {
      "id": "unit_economics.advise",
      "kind": "discoverable",
      "works": true,
      "mcp_tool": "invoke_manifest",
      "rest": "POST /api/invoke",
      "manifest_id": "ecorce:unit-economics-advisor@v1",
      "function_ref": "fn-ecorce-unit-economics"
    },
    {
      "id": "produce_pool.weekly",
      "kind": "transactional",
      "works": true,
      "mcp_tool": "invoke_manifest",
      "rest": "POST /api/invoke",
      "manifest_id": "ecorce:fruits-legumes-hebdo@v1",
      "function_ref": "fn-ecorce-fruits-legumes",
      "ui": "https://ecorce.app/p/ecorce/fruits-legumes-hebdo"
    },
    {
      "id": "offer.get",
      "kind": "discoverable",
      "works": true,
      "mcp_tool": "get_offer",
      "rest": "GET /api/offers/{id}"
    },
    {
      "id": "order_draft.create",
      "kind": "transactional",
      "works": true,
      "actor": "agent",
      "mcp_tool": "create_order_draft",
      "rest": "POST /api/drafts",
      "manifest_id": "ecorce:order-draft-engine@v1",
      "function_ref": "fn-ecorce-order-draft"
    },
    {
      "id": "order_draft.get",
      "kind": "transactional",
      "works": true,
      "actor": "agent",
      "mcp_tool": "get_draft",
      "rest": "GET /api/drafts/{id}"
    },
    {
      "id": "order_draft.confirm",
      "kind": "transactional",
      "works": true,
      "actor": "human only",
      "ui": "https://ecorce.app/essayer, https://ecorce.app/compte"
    },
    {
      "id": "order.place",
      "kind": "transactional",
      "works": true,
      "actor": "system after member confirmation",
      "target": "demo sink only (never a real partner)"
    },
    {
      "id": "opportunities.list",
      "kind": "discoverable",
      "works": true,
      "mcp_tool": "list_network_opportunities",
      "rest": "GET /api/opportunities"
    },
    {
      "id": "opportunities.join",
      "kind": "transactional",
      "works": true,
      "actor": "agent (draft) + human (confirm)",
      "mcp_tool": "join_network_opportunity",
      "rest": "POST /api/opportunities/join"
    },
    {
      "id": "tools.shared",
      "kind": "discoverable",
      "works": true,
      "mcp_tool": "list_shared_tools",
      "rest": "GET /api/shared-tools"
    },
    {
      "id": "surface.function.publish",
      "kind": "buildable",
      "works": true,
      "actor": "agent or partner",
      "mcp_tool": "publish_worker_function",
      "rest": "POST /api/functions",
      "runtime": "ecorce_surface"
    },
    {
      "id": "surface.function.call",
      "kind": "discoverable",
      "works": true,
      "actor": "agent",
      "mcp_tool": "call_worker_function",
      "rest": "POST /api/functions/call"
    },
    {
      "id": "tools.clone",
      "kind": "buildable",
      "works": true,
      "actor": "agent or partner",
      "mcp_tool": "clone_tool",
      "rest": "POST /api/shared-tools/clone"
    },
    {
      "id": "member.passkey",
      "kind": "identity",
      "works": true,
      "ui": "https://ecorce.app/compte"
    },
    {
      "id": "member.oauth",
      "kind": "identity",
      "works": true,
      "endpoint": "https://ecorce.app/member/mcp"
    },
    {
      "id": "mandate.read",
      "kind": "transactional",
      "works": true,
      "mcp_tool": "get_mandate",
      "endpoint": "member only"
    },
    {
      "id": "catalogue.ingest",
      "kind": "buildable",
      "works": true,
      "actor": "partner (key)",
      "rest": "POST /api/partners/{id}/ingest"
    },
    {
      "id": "tool.publish",
      "kind": "buildable",
      "works": true,
      "actor": "partner (key)",
      "rest": "POST /api/tools"
    },
    {
      "id": "tool.build",
      "kind": "buildable",
      "works": true,
      "actor": "partner (passkey)",
      "ui": "https://ecorce.app/partenaires",
      "rest": "POST /api/onboard/{partner}/tools/{generate|preview|publish}",
      "templates": "https://ecorce.app/api/tool-templates",
      "runtime": "ecorce_surface",
      "isolation": "no bindings, outbound blocked, 10 ms CPU, 1 subrequest"
    },
    {
      "id": "partner.onboard",
      "kind": "buildable",
      "works": true,
      "actor": "distributor or producer (passkey)",
      "ui": "https://ecorce.app/partenaires"
    },
    {
      "id": "recipes.list",
      "kind": "discoverable",
      "works": true,
      "mcp": "prompts/list, prompts/get",
      "resource": "ecorce://recipes.json"
    },
    {
      "id": "ui.generate",
      "kind": "discoverable",
      "works": true,
      "rest": "POST /api/ui",
      "ui": "https://ecorce.app/essayer"
    },
    {
      "id": "partner_tool.monde-naturel.connector",
      "kind": "buildable",
      "works": true,
      "partner_id": "monde-naturel",
      "name": "monde-naturel.connector",
      "description": "Example connector a distributor publishes: availability (including shared inter-distributor SPNs like SPN-EX-SAJA-010) and delivery windows. Stub with invented data.",
      "status": "stub (example data)",
      "runtime": "ecorce_surface",
      "template": null,
      "mcp_tools": [
        "monde_naturel__check_availability",
        "monde_naturel__get_delivery_windows"
      ],
      "tools": [
        {
          "name": "check_availability",
          "description": "Example availability for Le Monde au Naturel SPN ids (SPN-EX-MONDE-… and shared SPN-EX-SAJA-010). Accepts {spns: [...]} or {spn, qty}. Invented data.",
          "inputSchema": {
            "type": "object",
            "properties": {
              "spns": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "minItems": 1,
                "maxItems": 20
              },
              "spn": {
                "type": "string",
                "description": "single SPN id (alternative to spns)"
              },
              "qty": {
                "type": "integer",
                "minimum": 1,
                "description": "optional requested quantity"
              }
            },
            "additionalProperties": false
          }
        },
        {
          "name": "get_delivery_windows",
          "description": "Example delivery windows for a Québec postal code prefix (e.g. G9A). Invented data.",
          "inputSchema": {
            "type": "object",
            "properties": {
              "postal_prefix": {
                "type": "string",
                "pattern": "^[A-Za-z][0-9][A-Za-z]$"
              }
            },
            "required": [
              "postal_prefix"
            ],
            "additionalProperties": false
          }
        }
      ],
      "permissions": {
        "declared": [
          "read:own_catalogue"
        ],
        "receives": [
          "tool arguments only"
        ],
        "never_receives": [
          "member identity",
          "mandates",
          "other partners' data",
          "secrets"
        ],
        "network": "none required"
      }
    },
    {
      "id": "partner_tool.distribution-exemple-outils.minimum_order",
      "kind": "buildable",
      "works": true,
      "partner_id": "distribution-exemple-outils",
      "name": "Minimum de commande",
      "description": "Minimum de commande, seuil de livraison gratuite, règles par région (préfixe postal).",
      "status": "self-serve (example data)",
      "runtime": "ecorce_surface",
      "template": "minimum_order",
      "mcp_tools": [
        "distribution_exemple_outils__check_minimum_order"
      ],
      "tools": [
        {
          "name": "check_minimum_order",
          "description": "Does an order total (in cents, CAD) meet this partner's minimum, optionally for a postal prefix like G9A? Partner-declared rules, example data.",
          "inputSchema": {
            "type": "object",
            "properties": {
              "order_total_cents": {
                "type": "integer",
                "minimum": 0
              },
              "postal_prefix": {
                "type": "string"
              }
            },
            "required": [
              "order_total_cents"
            ],
            "additionalProperties": false
          },
          "outputSchema": {
            "type": "object",
            "properties": {
              "meets_minimum": {
                "type": "boolean"
              },
              "minimum_cents": {
                "type": "integer"
              },
              "missing_cents": {
                "type": "integer"
              },
              "free_delivery": {
                "type": "boolean"
              }
            }
          }
        }
      ],
      "permissions": {
        "declared": [
          "read:own_config"
        ],
        "receives": [
          "tool arguments only"
        ],
        "never_receives": [
          "member identity",
          "mandates",
          "drafts",
          "other partners' data",
          "secrets"
        ],
        "network": "none (outbound blocked by the platform)"
      }
    },
    {
      "id": "partner_tool.muse-demo.custom_function",
      "kind": "buildable",
      "works": true,
      "partner_id": "muse-demo",
      "name": "Calculateur vrac",
      "description": "Fonction fonctions sur mesure: paliers de remise au volume, frais de livraison, incitatif Each.app et calcul de prix net.",
      "status": "self-serve (example data)",
      "runtime": "ecorce_surface",
      "template": "custom_function",
      "mcp_tools": [
        "muse_demo__run_custom_function"
      ],
      "tools": [
        {
          "name": "run_custom_function",
          "description": "Run this partner's custom fonctions pricing, volume-tier, shipping, and Each.app incentive calculator (isolated function on the Écorce surface, example data).",
          "inputSchema": {
            "type": "object",
            "properties": {
              "qty": {
                "type": "number",
                "minimum": 1
              },
              "unit_price_cents": {
                "type": "integer",
                "minimum": 0,
                "description": "optional override in cents CAD; uses base_unit_price_cents if omitted"
              },
              "postal_prefix": {
                "type": "string"
              }
            },
            "required": [
              "qty"
            ],
            "additionalProperties": false
          },
          "outputSchema": {
            "type": "object",
            "properties": {
              "function_title": {
                "type": "string"
              },
              "qty": {
                "type": "number"
              },
              "applied_discount_pct": {
                "type": "number"
              },
              "subtotal_cents": {
                "type": "integer"
              },
              "net_Merchandise_cents": {
                "type": "integer"
              },
              "shipping_cents": {
                "type": "integer"
              },
              "total_cents": {
                "type": "integer"
              },
              "each_shopper_pool_cents": {
                "type": "integer"
              }
            }
          }
        }
      ],
      "permissions": {
        "declared": [
          "read:own_config"
        ],
        "receives": [
          "tool arguments only"
        ],
        "never_receives": [
          "member identity",
          "mandates",
          "drafts",
          "other partners' data",
          "secrets"
        ],
        "network": "none (outbound blocked by the platform)"
      }
    }
  ],
  "partners": [
    {
      "id": "saja",
      "role": "distributor",
      "name": "Groupe SAJA",
      "status": "pilot_target",
      "test_data": true
    },
    {
      "id": "monde-naturel",
      "role": "distributor",
      "name": "Le Monde au Naturel",
      "status": "pilot_target",
      "test_data": true
    },
    {
      "id": "ferme-exemple",
      "role": "producer",
      "name": "Ferme Exemple des Cantons (producteur fictif)",
      "status": "fictional_example",
      "test_data": true
    }
  ],
  "recipes": [
    {
      "id": "commande-hebdo",
      "title_fr": "Commande hebdo",
      "title_en": "Weekly order",
      "role": "retailer",
      "uses": [
        "catalogue.search",
        "order_draft.create"
      ],
      "mcp_prompt": "commande-hebdo",
      "arguments": [
        {
          "name": "liste",
          "description": "Ce que tu veux commander, ex. \"3 savon vaisselle 10 L, 2 lentilles\"",
          "required": true
        }
      ]
    },
    {
      "id": "reassort-seuil",
      "title_fr": "Réassort sous seuil",
      "title_en": "Restock below threshold",
      "role": "retailer",
      "uses": [
        "catalogue.search",
        "order_draft.create"
      ],
      "mcp_prompt": "reassort-seuil",
      "arguments": [
        {
          "name": "stock",
          "description": "Article, stock actuel, seuil, ex. \"lessive 10 L: 1 / seuil 3\"",
          "required": true
        }
      ]
    },
    {
      "id": "comparer-fournisseurs",
      "title_fr": "Comparer deux fournisseurs",
      "title_en": "Compare two suppliers",
      "role": "retailer",
      "uses": [
        "catalogue.search",
        "offer.get"
      ],
      "mcp_prompt": "comparer-fournisseurs",
      "arguments": [
        {
          "name": "produit",
          "description": "Ex. \"savon à mains 4 L\"",
          "required": true
        }
      ]
    },
    {
      "id": "annoncer-promo",
      "title_fr": "Annoncer une promo à mes détaillants",
      "title_en": "Announce a promo to my retailers",
      "role": "distributor",
      "uses": [
        "partners.list",
        "catalogue.search"
      ],
      "mcp_prompt": "annoncer-promo",
      "arguments": [
        {
          "name": "partner_id",
          "description": "Ton identifiant partenaire, ex. saja",
          "required": true
        },
        {
          "name": "promo",
          "description": "La promo, ex. \"10 % sur la lessive 20 L ce mois-ci\"",
          "required": true
        }
      ]
    },
    {
      "id": "optimiser-panier-et-livraison",
      "title_fr": "Optimiser mon panier et la livraison gratuite",
      "title_en": "Optimize cart, bulk & free shipping",
      "role": "retailer",
      "uses": [
        "catalogue.search",
        "order_draft.create"
      ],
      "mcp_prompt": "optimiser-panier-et-livraison",
      "arguments": [
        {
          "name": "panier",
          "description": "Ce que tu prévois commander et ton préfixe postal, ex. \"3 savon vaisselle 4 L chez SAJA, 2 lentilles chez Monde au Naturel, G9A\"",
          "required": true
        }
      ]
    },
    {
      "id": "activer-rotation-each",
      "title_fr": "Activer la sortie en caisse avec Each.app",
      "title_en": "Drive shelf velocity with Each.app",
      "role": "producer",
      "uses": [
        "catalogue.search"
      ],
      "mcp_prompt": "activer-rotation-each",
      "arguments": [
        {
          "name": "partner_id",
          "description": "Producteur ou distributeur, ex. ferme-exemple ou saja",
          "required": true
        },
        {
          "name": "budget",
          "description": "Enveloppe ou remise prévue, ex. \"10 % sur 20 caisses de sirop d'érable\"",
          "required": true
        }
      ]
    },
    {
      "id": "campagne-flotte-et-marque-ecorce",
      "title_fr": "Campagne flotte-média & marque Écorce",
      "title_en": "Fleet-as-media & shared Écorce brand",
      "role": "distributor",
      "uses": [
        "partners.list",
        "catalogue.search"
      ],
      "mcp_prompt": "campagne-flotte-et-marque-ecorce",
      "arguments": [
        {
          "name": "territoire",
          "description": "Préfixe postal et produit vedette, ex. \"G9A, sirop d'érable et savon en vrac\"",
          "required": true
        }
      ]
    }
  ],
  "shared_tools": [
    {
      "id": "shared-min-order-g9a",
      "alias_id": "shared-min-order",
      "template": "minimum_order",
      "name": "Minimum de commande & livraison gratuite régionale (Mauricie G9A)",
      "author_partner": "distribution-exemple-outils",
      "credit_fr": "Créé par Distribution Exemple Outils · utilisé par 4 membres (données d'exemple)",
      "credit_en": "Created by Distribution Exemple Outils · used by 4 members (example data)",
      "clones_count": 4
    },
    {
      "id": "shared-promo-vrac",
      "template": "promo",
      "name": "Promo de la semaine sur les formats 20 L en vrac",
      "author_partner": "saja",
      "credit_fr": "Créé par Groupe SAJA (exemple) · utilisé par 4 membres (données d'exemple)",
      "credit_en": "Created by Groupe SAJA (example) · used by 4 members (example data)",
      "clones_count": 4
    },
    {
      "id": "shared-dispo-saison",
      "template": "availability",
      "name": "Disponibilité des récoltes et produits locaux",
      "author_partner": "monde-naturel",
      "credit_fr": "Créé par Le Monde au Naturel (exemple) · utilisé par 2 membres (données d'exemple)",
      "credit_en": "Created by Le Monde au Naturel (example) · used by 2 members (example data)",
      "clones_count": 2
    }
  ],
  "network_opportunities": [
    {
      "id": "pool-mauricie-g9a",
      "kind": "logistics_consolidation",
      "title_fr": "Consolidation de tournée & livraison gratuite (Mauricie G9A & Montréal H2X)",
      "actors": [
        "distributeur (monde-naturel / saja)",
        "détaillants indépendants (secteurs G9A et H2X)"
      ],
      "target_cents": 50000,
      "current_committed_cents": 74000,
      "missing_cents": 0,
      "summary_fr": "Deux détaillants sur la même tournée du mardi/jeudi combinent leurs brouillons pour franchir le minimum de commande (500,00 $) et éliminer 100 % des frais de livraison. 740,00 $ engagés sur un seuil de 500,00 $ — minimum de commande collectif atteint pour la livraison gratuite.",
      "summary_en": "Two retailers on the same Tuesday/Thursday route pool their drafts to cross the $500.00 free-shipping threshold and cut delivery fees by 100%. $740.00 committed on a $500.00 threshold — collective free-shipping threshold reached."
    },
    {
      "id": "pool-flotte-ecorce",
      "kind": "fleet_media_co_op",
      "title_fr": "Campagne Flotte-Média Écorce cofinancée (Camions & bacs de livraison)",
      "actors": [
        "producteur (ferme-exemple)",
        "distributeur (monde-naturel)",
        "détaillants de la tournée"
      ],
      "target_cents": 120000,
      "current_committed_cents": 80000,
      "missing_cents": 40000,
      "summary_fr": "Le producteur (Ferme Exemple des Cantons) et le distributeur (Le Monde au Naturel) cofinancent l'affichage sous la bannière commune Écorce sur les camions et bacs de livraison qui sillonnent le quartier, pendant que les détaillants de la route mettent les produits en avant.",
      "summary_en": "The producer (Ferme Exemple) and distributor (Le Monde au Naturel) co-fund shared Écorce B2C branding on the delivery trucks and boxes serving the neighborhood while retailers feature the products in store."
    },
    {
      "id": "pool-activation-each",
      "kind": "b2c_activation_each",
      "title_fr": "Activation consommateur directe via Each.app (Zéro taxe publicitaire)",
      "actors": [
        "producteur / distributeur (saja, ferme-exemple)",
        "détaillants indépendants",
        "consommateurs (each.app)"
      ],
      "target_cents": 90000,
      "current_committed_cents": 60000,
      "missing_cents": 30000,
      "summary_fr": "Au lieu de perdre 8 % à 12 % du volume en intermédiaires publicitaires, le producteur et le détaillant convertissent l'enveloppe en incitatif direct dans le pass Each.app du client en magasin (débloqué uniquement sur un \"oui confirmé\" en caisse et partageable via \"Moi aussi\").",
      "summary_en": "Instead of losing 8–12% of volume to ad intermediaries, producer and retailer convert that spend into a direct perk in the shopper's Each.app pass in store (unlocked only on a confirmed yes at checkout and shareable via 'Moi aussi')."
    }
  ],
  "not_available": [
    "payment",
    "transmission to a real partner",
    "sending messages to retailers",
    "free-code partner tools (templates only)",
    "network access from partner tools"
  ]
}