Guides

Publish a project capability surface

Export bounded, versioned slices of your project for other projects to install - entities, operations, CLI commands, workflows, agent skills, analytics, events, webhooks, auth, and runtime handlers.

A project capability surface is a signed, versioned, audit-trailed slice of a Vadyl project. Provider projects publish typed slices. Consumer projects install them with explicit grants, billing attribution, runtime descriptor integration, and revocable lifecycle state.

1. Decide the surface boundary

Start with the capability you want other projects to depend on: an email service, payments service, LLM gateway, internal accounting plane, command pack, workflow library, analytics model, event vocabulary, or agent skill set. The boundary should be product-shaped, not provider-shaped.

2. Define the manifest

// vadyl.surface.ts in the provider project
export default defineProjectCapabilitySurface({
  name: "EmailService",
  version: "1.2.0",
  publisherProject: "acme/email-service",
  slices: {
    entities: ["EmailMessage", "EmailTemplate"],
    operations: ["email.send", "email.render", "email.scheduleAt"],
    cliCommands: ["email.send", "email.template.render"],
    workflows: ["sendCampaign"],
    agentSkills: ["draftCustomerEmail"],
    analyticsMeasures: ["emailsSent", "bounceRate"],
    events: ["email.sent", "email.bounced", "email.opened"],
    realtimeChannels: ["email.delivery"],
    webhookTopics: ["email.bounced", "email.complained"],
    associationTemplates: [{
      name: "MessageRecipient",
      relation: { from: "EmailMessage", to: "<consumer:User>" },
    }],
  },
  exposure: {
    protocols: ["Rest", "Sdk", "Cli", "Mcp", "Webhook", "Realtime", "Dashboard"],
    stability: "Stable",
    deprecationPolicy: { minimumWindow: "12mo" },
  },
  governance: {
    requiredGrants: ["surface:EmailService.install", "operation:email.send"],
    quotaDimensions: ["surface", "operation", "consumerProject"],
    billingAttribution: "consumer-project",
  },
});

3. Validate locally

vadyl surface validate ./vadyl.surface.ts
vadyl graph validate
vadyl surface explain EmailService --output json

Validation checks the selected slices, exposure bindings, CLI output contracts, SDK namespace projection, MCP tool schemas, PCG nodes, grant references, quota dimensions, lifecycle policy, and descriptor hash.

4. Publish

vadyl surface publish EmailService@1.2.0 --manifest ./vadyl.surface.ts

Publishing signs the ProjectCapabilitySurfaceManifest, registers a PublishedSurface, emits lifecycle events, and makes the version discoverable to projects allowed by the provider's publication policy. Published versions are immutable.

5. Install from a consumer project

vadyl surface install EmailService@1.2.0 \
  --publisher acme/email-service \
  --project storefront \
  --grant operation:email.send \
  --grant cli:email.send \
  --grant mcp:email.send \
  --billing-project storefront

The installation pins the provider version, narrows grants, declares billing attribution, records allowed protocols, and writes a branchableInstallationManifest. The consumer runtime descriptor now sees the installed surface as project capability.

6. Use through any projection

// SDK
await vadyl.surfaces.EmailService.email.send({
  to: user.email,
  template: "welcome",
  data: { user },
});

# CLI
vadyl email send --to ada@example.com --template welcome --data @data.json

# MCP
tools/call -> email_send

All three calls dispatch through the same exposure binding and produce the same consumption evidence. Protocols do not own separate semantics.

7. Observe usage and explain decisions

vadyl surface consumption EmailService --group-by consumerProject,operation
vadyl surface explain-consumption <consumptionId>
vadyl graph edges --from surface:EmailService

ProjectCapabilityConsumptionDescriptor records connect the provider project, consumer project, installation id, actor, grant, quota dimension, billing scope, protocol, correlation id, and reason block.

8. Deprecate, upgrade, revoke

vadyl surface deprecate EmailService@1.2.0 --replace-with 2.0.0 --window 12mo
vadyl surface upgrade EmailService --to 2.0.0 --project storefront
vadyl surface revoke EmailService@1.2.0 --reason "security replacement"

Deprecation warns without breaking installed consumers. Upgrade is an explicit consumer action and can be sandboxed. Revocation fails closed through project grants and runtime descriptors.

Federation vs installable surfaces

Federation is the lightweight per-entity directional grant for cross-project data access. Installable surfaces are the productized versioned package model for capability sets across entities, operations, commands, workflows, agents, analytics, events, and governance.

Reference details live in Project capability surfaces.