Skip to content

feat(den-api): grant-native capability index — chat-created skills usable without a marketplace (skill-sharing P1) - #3410

Merged
benjaminshafii merged 3 commits into
devfrom
feat/grant-native-skills
Aug 1, 2026
Merged

feat(den-api): grant-native capability index — chat-created skills usable without a marketplace (skill-sharing P1)#3410
benjaminshafii merged 3 commits into
devfrom
feat/grant-native-skills

Conversation

@benjaminshafii

Copy link
Copy Markdown
Member

What

Phase 1 of the Grant-Native Skill Sharing program (spec: prds/skill-sharing/grant-native-skill-sharing.md, included in this PR).

A skill created from the chat (create-skill builtin → POST /v1/plugins) was invisible and unexecutable in chat — even for its creator, who already holds a manager grant — because the capability index built its candidate set by inner-joining marketplace_plugin + marketplace. Grants only filtered; they never admitted.

This PR makes the index grant-native:

  • Candidate set = marketplace-attached rows (existing queries byte-identical) ∪ grant-only rows (new notExists active-membership query). Execute falls back to the grant-only resolver only when the marketplace resolver returns zero rows.
  • filterVisibleRows semantics unchanged: a row still requires a live config-object / plugin / (when present) marketplace grant. The deliberate no-admin-bypass behavior is preserved.
  • Payloads: marketplace is now string | null; summaries/hints degrade gracefully. Capability names never encoded the marketplace, so naming is untouched.
  • Desktop route GET /v1/resources/marketplace-capabilities keeps its non-null contract (grant-only rows filtered there; revisit in P3).
  • create-skill builtin copy: reports the skill is ready to use now instead of "private until published or shared".

No schema migrations. Marketplaces/catalogs unchanged.

Tests (commands + results)

cd ee/apps/den-api
bun test test/grant-native-capabilities.test.ts \
         test/marketplace-capabilities.test.ts \
         test/marketplace-cloud-readiness.test.ts \
         test/plugin-system-create-bundle.test.ts
# → 63 pass / 0 fail (5 new A1–A5 acceptance tests + 58 existing), 350 assertions
pnpm exec tsc --noEmit   # clean

New suite test/grant-native-capabilities.test.ts (real MySQL, same harness as marketplace-capabilities.test.ts): A1 creator grant → search/execute/descriptors work with marketplace: null; A2 team grant admits team members, forbidden for others; A3 zero grants stays inaccessible; A4 marketplace-attached payloads byte-identical; A5 catalog + direct grant → one match, catalog name wins.

Proof format

Per program-owner decision this program uses spec acceptance suites instead of fraimz; the spec records the P1 results section with the evidence. No video/fraimz attached — reproduce with the commands above (MySQL at 127.0.0.1:3306, per-suite DBs via pnpm --filter @openwork-ee/den-db db:push).

Next (specced, not built)

P2 share verbs in chat · P3 library UI + provenance · P4 sharing postures.

@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview Aug 1, 2026 3:26pm
openwork-den Ready Ready Preview Aug 1, 2026 3:26pm
openwork-den-worker-proxy Ready Ready Preview Aug 1, 2026 3:26pm
openwork-diagnostics Ready Ready Preview Aug 1, 2026 3:26pm
openwork-landing Ready Ready Preview, v0 Aug 1, 2026 3:26pm

@benjaminshafii

Copy link
Copy Markdown
Member Author

Spec-lane proof (evals/specs)

Added evals/specs/skill-grant-access.test.ts — proves P1 over the exact wire desktop chat uses (POST /v1/mcp/tokenPOST /mcp/agent, Streamable HTTP JSON-RPC tools/call), not just den-api unit suites:

  1. Owner creates a plugin+skill via POST /v1/plugins with no marketplaceId/orgWide (the create-skill builtin contract)
  2. search_capabilities (with and without type: "skills") finds it — no marketplace field on the match
  3. execute_capability returns the raw SKILL.md, marketplace: null
  4. A freshly invited member (real invitation → signup → verify → accept flow via ensureMemberSession) cannot discover it and gets the exact denial {"error":"forbidden","message":"You have not been granted access to this marketplace plugin capability."}
  5. Cleanup archives the plugin

Runs (verified against a pristine --reset demo seed)

pnpm --dir evals run spec specs/skill-grant-access.test.ts   # 1 passed (635ms)
pnpm --dir evals run spec                                    # full pr lane: 3 files / 5 tests passed
pnpm --dir evals run typecheck                               # clean
# without OPENWORK_EVAL_DEN_API_URL → 1 skipped (env-gated, CI-safe)

Full boot-and-run workflow is documented in prds/skill-sharing/grant-native-skill-sharing.md (P1 wire proof section). Note DEN_ORG_MODE=multi_org is required for the member-bootstrap signup flow.

Finding that feeds P4

hasPluginArchCapability ignores its capability argument — all plugin-arch capabilities are admin/owner-only today (access.ts:101-103). Member-level skill creation doesn't exist yet; P1's claim holds for whoever may create. The P4 pre-flight question is answered: the capability→role mapping is a stub to replace.

@benjaminshafii

Copy link
Copy Markdown
Member Author

Spec workflow hardening: ensureMemberSession (behaviors) now probes GET /v1/auth/login-options before attempting the invitation+signup bootstrap — on a single-org Den with signup disabled it fails fast with the exact fix (DEN_ORG_MODE=multi_org like demo:den, or DEN_SINGLE_ORG_ALLOW_PUBLIC_SIGNUP=true) instead of a cryptic single_org_signup_disabled. Covered by a new stub-server unit test (evals/packages/behaviors/test/ensure-member-session.test.ts); evals unit lane + the live spec + typecheck re-verified. Member-level creation itself is opened separately in #3411.

@benjaminshafii

Copy link
Copy Markdown
Member Author

Eval run (spec lane) on this branch — 2026-08-01T20:31:21Z

pnpm --dir evals run spec        # full pr project
# → 3 files / 5 tests passed (12.4s):
#   specs/skill-grant-access.test.ts   — the wire spec: owner creates skill via POST /v1/plugins,
#                                        search_capabilities + execute_capability over /mcp/agent,
#                                        marketplace:null payload, invited member denied (live den stack, pristine seed)
#   specs/egress-selective-deny.test.ts, specs/egress-tls12-only.test.ts

Den stack: den-api from this branch on :8790 (multi_org), seeded Acme demo org. den-api acceptance suites (63/63) + typecheck previously reported above.

@diff-warden diff-warden Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warden security clearance: clear. No new security issues found in this diff (2fa2118c92dc7afe88b1f51b4ffec236a0ef9a09). Automated clearance satisfies the required-review gate only — a human still reviews and merges. Analysis run

@benjaminshafii
benjaminshafii merged commit 5fa41c4 into dev Aug 1, 2026
26 of 28 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant