Skip to main content

Product, Offer & Entitlement Commands

Client-side commands for the ledger 17.4 namespaces. Every command here accepts the shared client options (--api-base, --api-key, --context, --profile, --json; see CLI Overview). Full flag lists are on the CLI Reference.

Every command below is a RENDER of one existing server route — no command computes an entitlement, a plan decision, or a catalog fact client-side. product get and entitlement show narrow an already-fetched array to one entry by id; that is the only client-side selection any of these commands perform.

Product​

The fleet-wide product-capability catalog. Privileged-only: a non-privileged persona (customer or company-admin) gets a 403 — use entitlement below for the company-scoped slice instead.

vagaris product list
vagaris product get <id-or-title>

product list renders GET /api/product-catalog verbatim. product get fetches the same catalog and selects the entry whose id or title matches (case-insensitive) — there is no single-item route on this resource.

Not implemented (server gap)​

product health, product dependencies, product releases and product consumers are not implemented. Each is a real gap in the server, not an oversight:

  • health — no route computes per-product health. The nearest cousin, feature dimensions (GET /api/companies/:id/features/:id/dimensions), is keyed by a feature id inside one company, not by a product id, and answers a different question.
  • dependencies — services/capability-graph.ts exports a listEdges reader, but no route anywhere in the server calls it; its only caller is its own module's genome-backfill job. There is nothing to render.
  • releases — GET /api/companies/:id/release-gate/:subjectSlug is a per-subject sign-off gate ("who must sign this change"), not a list of a product's releases.
  • consumers — no route inverts the capability-catalog/bindings relationship (that inversion lives in vagary-core's product-plane /bindings, outside this repo).

Entitlement​

This company's capability entitlement state — the plan gate plus the product-tier slice, for the four capabilities the server actually enforces (governed_act, agent_seat, external_secret_provider, cloud_federation).

vagaris entitlement list --company-id <company-id>
vagaris entitlement show <capability> --company-id <company-id>
vagaris entitlement effective --company-id <company-id>

All three render GET /api/companies/:companyId/product-tenant. list prints the entitlements[] array; show selects one row by capability id; effective prints the whole payload — the plan the refusals are measured against (companies.plan), the product-tier plan label, and every capability verdict together.

Not implemented (server gap)​

entitlement explain is not implemented. resolveCapabilityPlanRefusal (server/src/services/entitlement/capability-plan.ts) already computes the refusal reason, but no route exposes it standalone — its only callers are internal to the act-gate and route-entitlement seams. Building entitlement explain needs a new server route (e.g. GET /api/companies/:id/entitlement/explain?capability=) before this CLI can render it.

Offer​

Commercial offers this company has asked for (ADR-127: sales-assisted, qualified — never anonymous or self-provisioning).

vagaris offer agreement list --company-id <company-id>
vagaris offer agreement create --requested-offer <offer-id> --intent-type acquisition --origin-surface vagaris.org --company-id <company-id> [--source product] [--origin-product <slug>] [--requested-product <slug>] [--next-action "..."] [--note "..."]
vagaris offer agreement update <intent-id> --status qualified --company-id <company-id> [--note "..."]

An agreement is a commercial-intent record — the durable ask behind an offer (requested_offer), not the offer catalog itself. list and create render GET/POST /api/companies/:companyId/commercial-intent; update renders PATCH .../commercial-intent/:id, which moves only the client-settable qualification status (qualified, declined, withdrawn — settled is the billing rail's fact alone and cannot be set here). There is no agreement show: the server exposes list, create and update on this resource, but no get-by-id.

--intent-type and --origin-surface are validated client-side against the server's own zod enum before the request is sent, so a typo fails fast with a usage error instead of a round trip.

Not implemented (server gap)​

offer list and offer show are not implemented. The sellable-offer catalog (plans, pricing) is vagary-core's (/plans, /pricing-policy), and this server carries no proxy route for it — there is nothing in this API for a client of it to call.

offer effective and offer explain are deliberately not duplicated under offer. An offer has no effective/explain surface of its own; those questions are answered for the same company by entitlement effective (built) and entitlement explain (not yet built — see above).

Binding​

There is no binding namespace in this CLI. Product-to-capability bindings (list/get/plan/apply/configure/reconcile/suspend/migrate/retire) have zero routes anywhere in this server — that lifecycle lives entirely in vagary-core's product-plane (POST /bindings, GET /bindings, POST /bindings/:id/status), a different service this CLI does not talk to.