Expand description
MuxAPI handlers for the v1 standalone Skill primitive. skill.list / skill.get / skill.upsert / skill.delete / skill.bind / skill.unbind
Plus the Memory-level catalog (skill.catalog.): global skills only,
window-scoped — no agent_id, no check_s1 (mirrors bundle. auth
shape, since Memory has no agent connection context to gate on).
db_skills is authoritatively identity_store as of Phase 2 of
SPEC_DURABLE_BINDINGS_2026_09_10.md (§5.1/§5.4) — mstore stays the
ref-table owner (db_agent_skills_ref/db_bundle_skills_ref are not
promoted until Phase 3/6). Pure single-table reads/writes (skill_get,
skill_upsert_unique_global) call directly on identity_store; methods
that combine a ref table with the catalog now take identity_store as an
explicit catalog parameter while still being called ON mstore (the
ref-owning receiver).
Functions§
- register
- register_
skill_ 🔒bind - register_
skill_ 🔒catalog_ bind - register_
skill_ 🔒catalog_ bind_ to_ bundle - register_
skill_ 🔒catalog_ delete - register_
skill_ 🔒catalog_ list - register_
skill_ 🔒catalog_ list_ for_ agent - Catalog-tier sibling of
skill.list(above) — GLOBAL SKILLS ONLY, each annotated withbound_to_agentfor the caller-suppliedagent_id, nocheck_s1. AgentStashModal’s Skills tab (the per-agent Stash view) runs over the dashboard’s connection, which is never agent-authenticated, soskill.list’s gate can never be satisfied from that caller — the exact same reasoning asskill.catalog.bindabove. Deliberately does NOT reuseskill.list’s full computation (global + this agent’s own private skills): with nocheck_s1,agent_idis unverified, and a private skill’scontent/description/triggercan carry sensitive agent-authored material — returning it for an arbitrary caller-chosenagent_idwould be an IDOR into every agent’s private skills. SeeStore::skill_list_global_for_agent’s doc comment and docs/reports/REPORT_ARMORY_ARCHITECTURE_AND_NAMING_REVIEW_2026_07_23.md §2.2. - register_
skill_ 🔒catalog_ list_ for_ bundle - Bundle-scoped sibling of
skill.list— GLOBAL SKILLS ONLY plus this bundle’s own referenced skills, each annotated withbound_to_bundle. Nocheck_s1(a bundle has no agent identity to gate on). Deliberately restricted to global + bundle-bound rows only, same IDOR reasoning asskill_list_global_for_agent’s doc comment — seebundle_skill_list’s own implementation. - register_
skill_ 🔒catalog_ unbind - Catalog-tier sibling of
skill.unbind(above) — same DB write, nocheck_s1. Restricted to global rows only, matching the guardregister_skill_catalog_bind/register_skill_catalog_deletealready apply in this file: any window connection can sever any agent’s binding to a global skill (an intentional, pre-existing trust boundary — bind and delete already have the same or larger blast radius), but a private row’s own binding must not be touchable via this no-check_s1surface, even thoughskill_idis never exposed by any no-check_s1command today — defense in depth over relying solely on UUID secrecy. reagentx P1 on PR #2329 (round 2). - register_
skill_ 🔒catalog_ unbind_ from_ bundle - register_
skill_ 🔒catalog_ upsert - register_
skill_ 🔒catalog_ upsert_ for_ bundle - Creates a NEW, PRIVATE skill scoped directly to a bundle (never global)
— the bundle-level analog of
skill.upsert(agent-scoped). Seemcp.rs’sregister_mcp_catalog_upsert_for_bundlefor the full reasoning (reagentx P1 review on PR #2639). - register_
skill_ 🔒delete - register_
skill_ 🔒get - register_
skill_ 🔒list - register_
skill_ 🔒unbind - register_
skill_ 🔒upsert