# Dezycro Documentation > Customer documentation for Dezycro — AI-powered test management platform Dezycro turns any codebase into a documented, testable product — features with user-facing PRDs, technical TRDs, generated test cases, and live verification — driven from the web app or from the terminal via the Claude Code plugin. # Getting Started # Dezycro Documentation Welcome. Dezycro is an AI-powered specification + verification platform: write PRDs and TRDs, generate journey-based tests, run them with a per-feature verifier binary, and keep the whole workbook honest as you ship. Reading this as an AI agent? A machine-readable index of these docs is at [`/llms.txt`](https://docs.dezycro.ai/llms.txt), and the entire documentation as a single file at [`/llms-full.txt`](https://docs.dezycro.ai/llms-full.txt). Prefer those over scraping the rendered pages — every doc page also has a clean `.md` twin (append `index.md` to any page URL). ## What Dezycro does - **Authors PRDs and TRDs** via AI chat or the guided [`/dezycro:author`](https://docs.dezycro.ai/claude-code/skills/#dezycroauthor-doc-prd-doc-trd-revise-existing) flow — with a built-in quality gate that blocks broken TRDs from being approved. - **Generates journeys** (test scenarios grounded in your TRD intents) via [LogicStudio](https://docs.dezycro.ai/guides/test-management/index.md). - **Builds a per-feature verifier binary** from your OpenAPI spec — runs locally or in CI, asserts journey outcomes against your service. See [The Verifier](https://docs.dezycro.ai/concepts/verifier/index.md). - **Tracks decisions, issues, assumptions, tasks, and coverage** in a structured [workbook](https://docs.dezycro.ai/concepts/workbook/index.md) per feature — the source of truth for what's been decided, built, and proven. - **Surfaces gaps proactively** through the [Claude Code Plugin](https://docs.dezycro.ai/claude-code/index.md) — blocks tasks from going DONE without verifier evidence, nudges you to re-publish specs when controllers change, and auto-sweeps the workbook for decisions at wrap-up. ## Core workflow ``` Documents (upload) → Feature (PRD + TRD) → Journeys (LogicStudio) ↓ ↓ Workbook ←————————————————— Verifier runs (local / CI) (decisions, issues, tasks, coverage) ``` ## Surfaces - **Web app** — [app.dezycro.ai](https://app.dezycro.ai) — Mission Control, AI chat, LogicStudio, feature pages, settings - **Claude Code plugin** — `/dezycro:*` slash commands + Companion V2 background hooks ([install](https://docs.dezycro.ai/claude-code/install/index.md)) - **[MCP server](https://docs.dezycro.ai/api/mcp/index.md)** — for AI clients (Claude Code, Cursor, custom MCP) - **Public REST API** — `https://api.dezycro.ai/api/v1/...` for CI / custom integrations ## Getting started New to Dezycro? 1. [**Quick Start**](https://docs.dezycro.ai/getting-started/quick-start/index.md) — sign in, create a feature, generate tests, run the verifier. 1. [**Authentication & access**](https://docs.dezycro.ai/account/auth/index.md) — tenants, workspaces, PATs, BYOK. 1. [**Claude Code plugin**](https://docs.dezycro.ai/claude-code/index.md) — wire Dezycro into your editor. Already onboarded? - [**The Workbook**](https://docs.dezycro.ai/concepts/workbook/index.md) — the data model behind every feature - [**The Verifier**](https://docs.dezycro.ai/concepts/verifier/index.md) — how the per-feature binary works + CI integration - [**Companion V2**](https://docs.dezycro.ai/claude-code/companion/index.md) — the background loop that catches silent regressions - [**MCP server**](https://docs.dezycro.ai/api/mcp/index.md) — tool reference for programmatic access # Getting Started This section walks you through setting up Dezycro and running your first verify cycle end-to-end. ## Prerequisites - A Dezycro account ([sign up](https://app.dezycro.ai) — uses Google sign-in) - A product idea or existing documentation to work with - (Optional) A running service to point the verifier at ## Sections - [Quick Start](https://docs.dezycro.ai/getting-started/quick-start/index.md) — Set up your workspace, create your first feature, generate tests, and run the verifier. ## After the quick start - [Authentication & access](https://docs.dezycro.ai/account/auth/index.md) — tenants, workspaces, PATs, members, BYOK - [Claude Code Plugin](https://docs.dezycro.ai/claude-code/index.md) — drive Dezycro from your editor - [The Workbook](https://docs.dezycro.ai/concepts/workbook/index.md) — the data model behind every feature - [The Verifier](https://docs.dezycro.ai/concepts/verifier/index.md) — how the per-feature binary works + how to wire it into CI # Quick Start Get up and running with Dezycro in a few steps. ## 0. Sign in Visit [app.dezycro.ai](https://app.dezycro.ai) and click **Continue with Google**. On first sign-in, Dezycro creates your user record and provisions a tenant + a Default Workspace for you. See [Authentication](https://docs.dezycro.ai/account/auth/index.md) for tenant vs workspace, SSO, and PAT details. ## 1. Create a Workspace (optional) If the Default Workspace works for you, skip this. Otherwise, from the sidebar workspace switcher, click **Create Workspace** to add another (e.g. one per team). ## 2. Create a Project (optional) When you first sign up, Dezycro seeds a default **My First Project** for you — so you can skip this and use that. To organize work differently, create another from the sidebar: a project represents a product or feature area and contains all related features, PRDs, and tests. ## 3. Create a Feature Inside a project, create a feature. A feature is the smallest planned unit of behavior; it auto-creates two documents: **PRD** and **TRD**. You can author each document in three ways: - **AI chat** — Describe your requirements conversationally; the AI drafts a structured document. - **Manual** — Write from scratch using the editor. - **[`/dezycro:author`](https://docs.dezycro.ai/claude-code/skills/#dezycroauthor-doc-prd-doc-trd-revise-existing)** (Claude Code plugin) — Guided state machine that walks you through discovery → drafting → quality gate. Tip You can also upload existing documents to enrich the AI's understanding of your product. See [Document Ingestion](https://docs.dezycro.ai/guides/knowledge-base/index.md). ## 4. Generate Test Cases Open **LogicStudio** for your feature. Select the documents to generate tests from; Dezycro's AI produces test cases covering happy paths, edge cases, and negative scenarios. Review the generated tests, toggle individual cases on or off, and finalize when you're satisfied. ## 5. Run the Verifier Once your service implements the feature, **publish your OpenAPI spec** (from the feature page or via `/dezycro:publish-spec`) and **run the verifier**: - From the web UI's feature page, or - Via `/dezycro:verify` in the Claude Code plugin, or - In CI — see the [Verifier docs](https://docs.dezycro.ai/concepts/verifier/#running-the-verifier-in-ci) The verifier executes your journeys against the running service, asserts the responses match the spec + workbook expectations, and uploads results. Once all enforced journeys pass — and the workbook's issue, task, and coverage gates are clear — the feature auto-transitions to **VERIFIED**. ## What next? - Wire the [Claude Code plugin](https://docs.dezycro.ai/claude-code/index.md) into your editor for the day-to-day flow. - Read about the [Workbook](https://docs.dezycro.ai/concepts/workbook/index.md) — the structured record of what's been decided, built, and verified for each feature. - Set up [auth fixtures](https://docs.dezycro.ai/concepts/verifier/#personas-authlocaljson) so the verifier can authenticate as your test users. # Account & Billing # Authentication & access Dezycro accounts use standard OIDC. For day-to-day humans, **Google login** is the recommended path. For programmatic access (CI, scripts, the Claude Code plugin), use a **Personal Access Token (PAT)**. ## Logging in Visit [app.dezycro.ai](https://app.dezycro.ai) and click **Continue with Google**. On first sign-in, Dezycro creates your user record and (if you're the first member) provisions a new **tenant** (organization-level container) with a **Default Workspace** inside it. ### Tenant vs Workspace A common confusion — these are not the same: - **Tenant** — the organization-level entity. Every user belongs to exactly one tenant. Billing, members, SSO, and PATs are scoped here. - **Workspace** — a logical grouping *inside* a tenant. Tenants can have many workspaces (e.g. one per team). Projects, features, PRDs, tests, and verifier runs live inside workspaces. When the docs say "your tenant," that's your organization. When they say "your workspace," that's the inner container. ### SSO (Enterprise) Enterprise tenants can configure their own OIDC identity provider (Okta, Auth0, Azure AD, etc.) so users sign in via the customer's own SSO. Contact sales to enable. ## Personal Access Tokens (PATs) PATs let you authenticate as yourself to the Dezycro public API and MCP server without going through the OAuth flow. Use them for: - The Claude Code plugin (the MCP server reads `Authorization: Bearer dzy_…` headers) - CI scripts that hit the public API - Local tooling ### Creating a PAT 1. Sign in to [app.dezycro.ai](https://app.dezycro.ai) 1. Open **Settings → Personal Access Tokens** 1. Click **Create token** — give it a name and an optional expiry 1. Copy the token immediately — it's shown once and can't be retrieved later PAT format: `dzy_`. Token strings are bearer-style; pass as `Authorization: Bearer dzy_…` on every request. ### Token scopes PATs inherit your role within each workspace — a viewer's PAT can only read; a workspace admin's PAT can write. Tenant-scope settings (members, billing) require the **tenant owner** role. ### Revoking a token From the same **Personal Access Tokens** page, click **Revoke** next to the token. Revocation is immediate — in-flight requests with that token start returning 401 on the next call. ## Members & roles Roles are scoped per **workspace** (a user can have different roles in different workspaces of the same tenant): | Role | Permissions | | ---------- | -------------------------------------------------------------------------------------------- | | **Admin** | Full control of the workspace — invite/remove members, configure settings, edit all projects | | **Editor** | Create and edit projects, features, PRDs, TRDs, run verifier; cannot manage members | | **Viewer** | Read-only access; can view but not modify any workspace content | Tenant-level admin (manages members, billing, SSO config) is held by the **tenant owner** — usually the first user to sign up for the tenant. Contact support to transfer ownership. ### Inviting members From the workspace **Members** tab, click **Invite** and enter an email + role. The invitee gets an email link; on first sign-in they're added with the chosen role. If the invitee isn't already in your tenant, the invitation creates a tenant-level membership for them too — with no workspace access until they accept individual workspace invitations. ## Bring Your Own Key (BYOK) — Pro and above Tenants on **Pro, Team, or Enterprise** can supply their own LLM provider credentials (Anthropic / OpenAI / Bedrock / Vertex / Azure OpenAI) so all AI calls go through *your* billing account, not Dezycro's. Configure under **Settings → LLM Configuration**. Two test buttons (per-model + per-credential) let you verify connectivity before activating. Once activated: - All tenant-facing LLM calls (PRD chat, TRD authoring, test generation, workbook sweeps) bill to your provider - Token usage is no longer counted against your Dezycro plan's monthly cap - Embedding calls (document ingestion, retrieval) run on shared infrastructure and are unaffected — they don't consume your tokens either way BYOK is not available on the Free tier. ## Audit logs Every meaningful tenant action is logged: member invites, role changes, document edits, PAT creation/revocation, settings changes, SSO config changes, BYOK config changes. Audit logs are available on **Team and Enterprise** plans. View under **Settings → Audit Log** (visible to Tenant Owner and workspace Admins). Retention: - **Team plan:** 90 days - **Enterprise:** 1 year (or custom) Filterable by actor, action type, date range, resource type. Exportable as CSV. # Billing & plans Dezycro is sold per-seat with a monthly AI token allowance that scales with your seat count. All paid tiers ship with the full product surface — what differs is the price model, seat structure, monthly token budget, and a few high-touch features (SSO, audit logs). ## Plans | | **Free** | **Pro** | **Team** | **Enterprise** | | --------------------------------- | ------------------- | --------------------------------- | ------------------------------ | ------------------------------- | | Price | $0 / month | **$20 / month** (1 billable user) | **$39 / user / month** (min 3) | Custom (target $150–300 / user) | | AI tokens / billable user / month | 2M | 15M | 40M | Unlimited or BYOK | | Daily token cap | 200K | — | — | — | | Workspaces | 1 | 5 | Unlimited | Unlimited | | Projects per workspace | 1 | Unlimited | Unlimited | Unlimited | | Features per project | 3 | Unlimited | Unlimited | Unlimited | | Notebooks per workspace | 1 | 3 | Unlimited | Unlimited | | Pages per notebook | 1 (max 5,000 chars) | 15 | Unlimited | Unlimited | | Notebook directories | — | ✓ | ✓ | ✓ | | Billable users | 1 | 1 (Owner only) | Unlimited, subject to cap | Unlimited, subject to cap | | Viewers | — | Unlimited, free | Unlimited, free | Unlimited, free | | SSO | — | — | — | ✓ | | BYOK (your own LLM keys) | — | ✓ | ✓ | ✓ | | Audit log | — | — | ✓ (90-day retention) | ✓ (1-year or custom retention) | Public pricing: [dezycro.ai/pricing](https://dezycro.ai/pricing). **Tokens reset monthly.** Your tenant's monthly budget is `paidSeats × monthlyTokensPerSeat` — e.g. a Team plan with 4 seats has a 160M token allowance pooled across the tenant. The 200K daily cap is a Free-tier anti-abuse measure only. ## Roles, seats, and what counts Dezycro has two role hierarchies and one billing concept that ties them together. ### Tenant role Organization-wide — applies across every workspace. | Tenant role | Billable? | What they can do | | ----------- | --------- | --------------------------------------------------------- | | **Owner** | ✓ | Everything, including billing & cap management | | **Admin** | ✓ | Everything except billing | | **Member** | ✓ | Create + edit content in any workspace they belong to | | **Viewer** | ✕ | Read-only across the tenant. **Does not consume a seat.** | ### Workspace role Per-workspace — `Admin` / `Editor` / `Viewer`. Workspace roles are a finer-grained permission set *inside* a single workspace; they don't affect billing on their own. A user with **tenant role Viewer** is constrained to **workspace role Viewer** in every workspace — you can't promote them to workspace Editor without first promoting them to tenant Member. ### Billable user A user whose **stored tenant role** is `Owner`, `Admin`, or `Member`. Stored — not effective. (See [Pro role facade](#pro-role-facade) for why that distinction matters.) Viewers are not billable. Your Stripe subscription quantity is kept in sync with the billable count automatically (see [Auto-seat below](#auto-seat-team-only)) — there is no manual "add seat" / "remove seat" flow. ## Pro role facade The Pro plan supports **one billable user — the Owner** — but doesn't force you to delete or demote other members. The way this works at runtime: - **Stored roles are never mutated by plan changes.** When you upgrade Team → Pro, every existing member keeps their stored `Member` / `Admin` / workspace role in the database. - **At request time**, when `tenant.tier == PRO`, every **non-Owner** user is treated as `Viewer` — both tenant role and workspace role — regardless of what's stored. The transformation runs at the central auth layer (every service sees the same view) and on the user's `/me` endpoint (so the UI shows what they can actually do). This makes Pro fully **reversible**: - Upgrade Team → Pro → other members go view-only, no data lost. - Downgrade Pro → Team → every member's stored role becomes their effective role again, instantly. No migration step. On the billing page, Pro tenants with more than 1 stored billable user see: > "N members are stored as Member/Admin but are view-only on Pro. Upgrade to Team to restore their roles." ## Auto-seat (Team only) Pro is a flat plan: quantity is always 1, regardless of how many users exist. Auto-seat applies to **Team**: - **Adding a billable user** (invite a new Member, or promote a Viewer to Member/Admin): - If `billableUserCount > 3` → Stripe quantity is incremented by 1, prorated immediately. - If `billableUserCount ≤ 3` → no Stripe change. You're already paying the 3-seat floor. - **Removing a billable user** (delete, or demote to Viewer): - If `billableUserCount (after) ≥ 3` → Stripe quantity is decremented by 1, effective at the end of the current period (no immediate refund). - If `billableUserCount (after) < 3` → no Stripe change. Quantity stays at the 3-seat floor. In short: **Team always pays for at least 3 seats**. Below that, you have paid-for headroom you can use any time without changing your bill. Stripe quantity sync is atomic per-tenant, so rapid invites are coalesced into a single Stripe call and concurrent role changes can't race past the cap. ## Billable-user cap (Team & Enterprise) To protect against an over-eager admin doubling your monthly bill, the Owner can set a **`maxBillableUsers` cap** — a hard upper bound on the billable user count. Independent of Stripe quantity: the cap controls *consumption*, not *payment*. - **Owner-only.** Only users with `BILLING_MANAGE` permission can set or change it — by default, just the tenant Owner. - **Applies on Team and Enterprise only.** Setting a cap on Free or Pro returns `CAP_NOT_SUPPORTED` (Pro is structurally capped at 1 by the facade; Free is single-user). - **Lower bound** = `max(currentBillableUserCount, tier.seatFloor)`. We never auto-demote — you can't shrink the cap below what's already used. (`CAP_BELOW_USAGE` if you try.) - **Upper bound** = none. Set to `null` for unlimited. - **Stripe quantity** is unaffected by cap changes. **What happens when the cap is reached?** | Path | Behavior | | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | **Admin invite / role promotion** (`POST /api/manage/users`, `PUT /api/manage/users/{id}/role`) | Hard block — HTTP 400 `BILLABLE_CAP_REACHED`. Admin must re-invite with `Viewer` role. | | **User self-join** (OAuth callback, invitation acceptance, domain auto-join) | Soft fallback — user is shown a dialog explaining the cap is reached and offered to join as a Viewer instead. Requires explicit consent. | Cap state is updated atomically per tenant, so concurrent self-joins can't squeeze past it. ### Setting the cap **Organization Settings → Billing → Billable user cap.** UI shows current cap (or "Unlimited") with a hint like *"You're using N of M cap"*. Admins (non-owner) see the value but can't edit. Members and Viewers don't see this section. ## Upgrade & downgrade ### Free → Pro Billing page shows: *"$20/mo for 1 billable user. Unlimited free Viewers."* If you already have more than 1 billable user, you also see a warning that the others will become view-only via the Pro facade until you upgrade to Team. ### Free / Pro → Team Billing page shows a per-seat cost preview computed at checkout: - `billableUserCount ≥ 3` → "You have N billable members. Starts at N × $39/seat/mo = $(N × 39)/mo." - `billableUserCount < 3` → "Team requires a minimum of 3 seats. You have N billable members. Starts at 3 × $39 = $117/mo. You can invite up to (3 − N) more members without increasing your bill." You must acknowledge the line item before checkout. ### Team → Pro Stored roles are not touched. Other members go view-only at runtime via the facade. Stripe quantity drops to 1. ### Paid → Free (cancellation, payment failure) - Tenant tier flips to FREE; subscription stops. - Free's limits apply: 1 workspace, 1 project per workspace, 3 features per project, 1 user total, 2M tokens / mo, 200K daily cap. - **Existing resources above those limits are preserved** but read-only. You can't create more or invite new users until you upgrade. - Any `maxBillableUsers` cap is cleared (it doesn't apply on Free). - The admin sees a warning summarizing what's now past the limit and prompting an upgrade. ### Stripe portal **Organization Settings → Billing → Manage subscription** opens the Stripe customer portal: update payment method, download invoices, change plan (upgrades prorate immediately; downgrades apply at next renewal), or cancel. The "Manage subscription" link is gated by **`BILLING_MANAGE`** permission — Owner-only by default. ## What counts toward your AI token allowance Your monthly budget is **`paidSeats × monthlyTokensPerSeat`**, pooled across the tenant — anyone in the tenant draws from the same bucket. | Operation | Typical tokens / call | | ----------------------------------- | --------------------- | | Test case generation (from TRD) | 20,000–50,000 | | AI chat messages (PRD editing) | 1,000–5,000 | | AI autocomplete (in-editor) | 500–2,000 | | `/dezycro:author` PRD/TRD authoring | 5,000–30,000 | | Workbook sweeps (Companion) | 2,000–8,000 | ### What does NOT count - Document upload + ingestion (embeddings run on shared infra) - Vector search retrievals - Reading the workbook, listing features, navigating the UI - Verifier binary execution (runs locally; no LLM) ### Hitting the cap - The in-flight LLM call is allowed to complete. - Subsequent LLM-gated actions return: *"Monthly AI token allowance exhausted. Upgrade to continue."* - Non-LLM features (workbook editing, test runs, verifier, document upload, navigation) keep working. Upgrade or add seats at any time from the Stripe portal — the new allowance applies immediately. ## Subscription status API For programmatic access, `GET /api/billing/subscription-status` returns: | Field | Meaning | | ---------------------- | --------------------------------------------------------------- | | `tier` | `FREE` / `PRO` / `TEAM` / `ENTERPRISE` | | `paidSeats` | Stripe quantity (Pro=1, Team=`max(billableMembers, 3)`, Free=0) | | `billableMembers` | Stored Owner + Admin + Member count | | `viewerCount` | Stored Viewer count | | `pricePerSeatCents` | `2000` (Pro), `3900` (Team), custom (Ent), `null` (Free) | | `seatFloor` | `1` (Pro), `3` (Team), `null` (Free) | | `monthlyTokensPerSeat` | `2_000_000` / `15_000_000` / `40_000_000` / `null` (Ent BYOK) | | `dailyTokenCap` | `200_000` (Free), `null` otherwise | | `maxBillableUsers` | The Owner-set cap, or `null` if uncapped | | `currentPeriodEnd` | Renewal date as Unix epoch seconds | ## Audit trail Every billing-affecting action lands in the [audit log](https://docs.dezycro.ai/account/auth/#audit-logs): | Action | When it fires | Key metadata | | --------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------- | | `SEAT_ADDED` | Billable user created or promoted into a billable role | user, new quantity, prorated amount, `floorHeadroomUsed` | | `SEAT_REMOVED` | Billable user deleted or demoted to Viewer | user, new quantity, `flooredAtMinimum` | | `PLAN_UPGRADED` | `checkout.session.completed` webhook | old tier, new tier, billable count, starting quantity, users affected by facade | | `PLAN_DOWNGRADED` | Subscription cancelled or payment failure | old tier, new tier, reason | | `BILLING_CAP_CHANGED` | Owner edits `maxBillableUsers` | `oldCap`, `newCap`, current billable count, `paidSeats` | ## BYOK (Pro and above) Tenants on Pro, Team, or Enterprise can avoid Dezycro's token meter entirely by configuring [BYOK](https://docs.dezycro.ai/account/auth/#bring-your-own-key-byok-pro-and-above) — all AI calls go to your own provider account and are billed there. Your Dezycro invoice becomes just the seat fee. Enterprise contracts are set up by sales: Stripe subscription quantity and price are negotiated upfront. Auto-seat still runs (role changes adjust quantity within the negotiated bounds), but pricing is not enforced by the application. [Contact sales](mailto:sales@dezycro.ai) for Enterprise pricing. # Guides # CI Setup This page walks through wiring Dezycro into your CI pipeline end-to-end: ingesting your OpenAPI spec on every release, running Dezycro-generated tests with proper persona auth on every PR, and tying it all back to your project's workbook. We use a fictional `widgets-api` (Quarkus, OIDC-secured) as the running example so every snippet has somewhere real to land. Replace the names and URLs with yours. **Two reusable actions** live at [github.com/Dezycro/github-actions](https://github.com/Dezycro/github-actions). The rest of this guide is about how to assemble them. ## What the finished pipeline looks like ``` push to main pull_request │ │ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │ build app + run │ │ build app + run │ │ /q/openapi dump │ │ container │ └────────┬─────────┘ └────────┬─────────┘ │ │ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │ ingest-to-dezycro│ │ run-dezycro-tests│ │ source-type= │ │ pulls latest │ │ OPENAPI │ │ test image and │ └────────┬─────────┘ │ runs as personas │ │ └────────┬─────────┘ ▼ │ Dezycro regenerates ▼ journeys & test cases Results in workbook PR status check ``` Two pipelines, both terminating in the workbook: one **publishes the API shape**, the other **validates behavior** against it. ## Prerequisites Before either action will work you need: 1. **A Dezycro project** with PRDs and TRDs already created. 1. **An OpenAPI spec served by your app**. The [OpenAPI Specs guide](https://docs.dezycro.ai/guides/openapi-specs/index.md) covers the per-framework setup (Quarkus + SmallRye is what we recommend, and what `widgets-api` uses). 1. **A Dezycro PAT** with API scope — generate it under **Settings → API Tokens** in [app.dezycro.ai](https://app.dezycro.ai). 1. **A registry PAT** that can pull the test image (only needed for `run-dezycro-tests`). The next two sections cover the rest — defining the personas your tests will run as, and collecting the IDs CI needs to refer to your org / workspace / project. ## Define your personas CI runs Dezycro-generated tests as named users (`admin1`, `user1`, `readonly1`, …). Each one is a **persona** with a role, a description, and an auth strategy — defined in **Organization Settings → Test Personas** in the app. For `widgets-api` we'd create three: - `admin1` — can create, list, and delete widgets - `user1` — can create and list, but not delete - `readonly1` — can only list (drives negative-case assertions like "POST should 403") For each persona, you set: - **Name** — must match the persona name your tests reference - **Description** — the test generator reads this to assign personas to journeys, so be specific about what this user *can* and *cannot* do - **Auth type** — `HTTP_ENDPOINT`, `BEARER`, `HEADER`, `BASIC`, `JS`, or `NONE`. Picks the shape of the credential the verifier expects at run time. - **Environment variable** — the `AUTH_` env var the verifier will read at run time. This is the secret CI will populate. Configure personas before generating tests The test generator decides *which* persona drives each journey at generation time. If your project has no personas (or only `default`), every journey runs unauthenticated and won't reach any endpoint behind auth. **Set personas up first**, then trigger test generation. For the full conceptual reference — including the auth-type catalog (what JSON each type expects), local-dev `.dezycro/auth.local.json` setup, and persona design tips — see the [Personas & Auth guide](https://docs.dezycro.ai/guides/personas/index.md). ## Finding your IDs in the app Three IDs feed into the workflow file. Each one has a copy button in the UI. **Organization Settings → Team tab**. Look for the **Organization** card; click the chip next to "Organization ID" to copy. Used by `run-dezycro-tests` to locate the test image at `registry.dezycro.ai//:latest`. **Organization Settings → Workspace tab**. Click the **Workspace ID** chip next to the "Workspace Members" heading. Used by `ingest-to-dezycro` — documents land under a specific workspace. Open the project. The **Project ID** chip sits next to the project title at the top of the page. Used by both actions — `ingest-to-dezycro` to bind documents to the project, `run-dezycro-tests` to identify which project's tests to pull. ## Secrets and variables Set these once on your repository. We use GitHub Actions UI as the example; Forgejo / GitLab / Bitbucket are identical concepts under different names. ### Repo variables (non-secret IDs) | Variable | Source | Purpose | | ------------------------- | ------------------------------------------------------------ | ------------------------------------------- | | `DEZYCRO_ORGANIZATION_ID` | [Org ID copy chip above](#finding-your-ids-in-the-app) | Identifies the test image to pull | | `DEZYCRO_WORKSPACE_ID` | [Workspace ID copy chip above](#finding-your-ids-in-the-app) | Identifies where docs ingest | | `DEZYCRO_PROJECT_ID` | [Project ID copy chip above](#finding-your-ids-in-the-app) | The project to ingest into / pull tests for | ### Repo secrets | Secret | What it holds | | ------------------------ | ---------------------------------------------------------- | | `DEZYCRO_API_TOKEN` | The Dezycro PAT | | `DEZYCRO_REGISTRY_TOKEN` | The registry PAT | | `AUTH_ADMIN1` | Pre-resolved auth-config **JSON** for the `admin1` persona | | `AUTH_USER1` | Same shape, for `user1` | | `AUTH_READONLY1` | Same shape, for `readonly1` | ### What goes in each `AUTH_` secret The **entire JSON config** for that persona — same shape as the `config` block in `.dezycro/auth.local.json`, but on a single line and with secrets pre-substituted. For `widgets-api`, `AUTH_ADMIN1` holds: ``` {"url":"https://auth.acme.example/oauth/v2/token","method":"POST","headers":{"Content-Type":"application/x-www-form-urlencoded"},"body":"grant_type=password&client_id=widgets-api&username=admin@acme.example&password=hunter2","tokenPath":"access_token","headerName":"Authorization","headerPrefix":"Bearer "} ``` `AUTH_USER1` and `AUTH_READONLY1` are the same shape with `username` and `password` swapped. For `BEARER` personas it's simpler — `{"token": "..."}`; for `NONE`, just `{}`. The full per-auth-type shape catalog is in [Personas & Auth → Auth types](https://docs.dezycro.ai/guides/personas/#auth-types). **Storing the JSON cleanly:** - **Single-line JSON** in the secret. Use a minifier locally: `jq -c . < admin1.json | pbcopy`. - If your secret store strips characters (some do), **base64-encode the JSON** instead and decode it into the env var at workflow level. ## Pipeline 1: Ingest the OpenAPI spec on `main` Whenever `main` advances, push the freshest spec into Dezycro so journey generation tracks the real API shape. .github/workflows/dezycro-ingest.yml ``` name: Dezycro — ingest spec on: push: branches: [main] jobs: ingest: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: distribution: temurin java-version: '21' - name: Build and start widgets-api run: | ./gradlew quarkusBuild java -jar build/quarkus-app/quarkus-run.jar & echo $! > /tmp/app.pid until curl -sf http://localhost:8080/q/health; do sleep 1; done - name: Dump OpenAPI spec run: curl -sf 'http://localhost:8080/q/openapi?format=json' > api-spec.json - uses: Dezycro/github-actions/ingest-to-dezycro@main with: token: ${{ secrets.DEZYCRO_API_TOKEN }} workspace-id: ${{ vars.DEZYCRO_WORKSPACE_ID }} project-id: ${{ vars.DEZYCRO_PROJECT_ID }} paths: api-spec.json source-type: OPENAPI - name: Stop widgets-api if: always() run: kill "$(cat /tmp/app.pid)" || true ``` The upload is **upsert by document name** (`overrideByName=true`), so re-runs replace the previous spec rather than piling up duplicates. Dezycro re-derives journey execution plans from the new spec and the test generator picks up any new endpoints on its next run. You can ingest other documents (PRDs, TRDs, runbooks, ADRs) the same way — just drop `source-type` and adjust `paths`. The default `source-type` is `DOC`. ## Pipeline 2: Run generated tests on every PR This is the main quality gate. Spin up your service, point `run-dezycro-tests` at it with the right persona credentials, fail the PR if anything regresses. .github/workflows/dezycro-test.yml ``` name: Dezycro — E2E tests on: pull_request: jobs: e2e: runs-on: ubuntu-latest services: widgets-api: image: ghcr.io/acme/widgets-api:${{ github.sha }} ports: ['8080:8080'] env: QUARKUS_PROFILE: ci steps: - uses: Dezycro/github-actions/run-dezycro-tests@main env: AUTH_ADMIN1: ${{ secrets.AUTH_ADMIN1 }} AUTH_USER1: ${{ secrets.AUTH_USER1 }} AUTH_READONLY1: ${{ secrets.AUTH_READONLY1 }} with: api-url: http://localhost:8080 organization-id: ${{ vars.DEZYCRO_ORGANIZATION_ID }} project-id: ${{ vars.DEZYCRO_PROJECT_ID }} registry-token: ${{ secrets.DEZYCRO_REGISTRY_TOKEN }} ``` What happens under the hood: 1. The action pulls `registry.dezycro.ai//:latest` — your project's compiled test image. 1. Forwards every `AUTH_*` env var on the step into the container. 1. The verifier inside the container reads `AUTH_CONFIG` (compiled in from your project's persona setup), then for each persona looks at the matching `AUTH_` env var and uses it to obtain a token (or apply static headers). 1. Runs every generated journey, attaches results to the workbook, exits non-zero on failure. The PR check shows pass / fail and links into the run in [app.dezycro.ai](https://app.dezycro.ai). ## Pipeline 3: Combined "build, ingest, test" If your service builds cleanly and you have the room, do everything in one workflow: .github/workflows/dezycro.yml ``` name: Dezycro on: push: branches: [main] jobs: full: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-java@v4 with: { distribution: temurin, java-version: '21' } - name: Build app run: ./gradlew quarkusBuild - name: Start app and capture spec run: | java -jar build/quarkus-app/quarkus-run.jar & echo $! > /tmp/app.pid until curl -sf http://localhost:8080/q/health; do sleep 1; done curl -sf 'http://localhost:8080/q/openapi?format=json' > api-spec.json - uses: Dezycro/github-actions/ingest-to-dezycro@main with: token: ${{ secrets.DEZYCRO_API_TOKEN }} workspace-id: ${{ vars.DEZYCRO_WORKSPACE_ID }} project-id: ${{ vars.DEZYCRO_PROJECT_ID }} paths: api-spec.json source-type: OPENAPI - uses: Dezycro/github-actions/run-dezycro-tests@main env: AUTH_ADMIN1: ${{ secrets.AUTH_ADMIN1 }} AUTH_USER1: ${{ secrets.AUTH_USER1 }} AUTH_READONLY1: ${{ secrets.AUTH_READONLY1 }} with: api-url: http://localhost:8080 organization-id: ${{ vars.DEZYCRO_ORGANIZATION_ID }} project-id: ${{ vars.DEZYCRO_PROJECT_ID }} registry-token: ${{ secrets.DEZYCRO_REGISTRY_TOKEN }} - name: Stop app if: always() run: kill "$(cat /tmp/app.pid)" || true ``` This is good for small services where the spec ingest and test run can share one build of the app. ## Per-environment credentials The same persona usually needs different credentials per environment (dev vs. staging vs. prod). Two patterns: 1. **Different secrets per environment.** Use [GitHub environment secrets](https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions#using-environment-secrets) — the same `AUTH_ADMIN1` name resolves to different values depending on the job's `environment:` setting. 1. **Different env var names per environment.** `AUTH_ADMIN1_DEV` vs `AUTH_ADMIN1_STAGING`, then conditionally map: `env: { AUTH_ADMIN1: ${{ matrix.env == 'staging' && secrets.AUTH_ADMIN1_STAGING || secrets.AUTH_ADMIN1_DEV }} }`. Pick whichever matches how your CI is already structured. ## Action references ### `ingest-to-dezycro` | Input | Required | Default | Description | | -------------- | -------- | ---------------- | --------------------------------------------------------------- | | `token` | yes | — | Dezycro API PAT | | `workspace-id` | yes | — | Workspace ID | | `project-id` | yes | — | Project ID to associate documents with | | `paths` | yes | — | Newline-separated file paths/globs to ingest | | `endpoint` | no | `api.dezycro.io` | API host (no protocol, no trailing slash) | | `source-type` | no | `DOC` | Document source type (`DOC`, `OPENAPI`, …) | | `insecure` | no | `false` | Skip TLS verification (dev environments with self-signed certs) | ### `run-dezycro-tests` | Input | Required | Default | Description | | ------------------- | -------- | --------------------- | ----------------------------------------------------------- | | `api-url` | yes | — | Base URL of the API under test | | `organization-id` | no¹ | — | Dezycro organization ID | | `project-id` | no¹ | — | Dezycro project ID | | `image` | no¹ | — | Full image ref — overrides `organization-id` / `project-id` | | `registry-host` | no | `registry.dezycro.ai` | Docker registry host | | `registry-token` | no | — | PAT for registry auth | | `registry-username` | no | `pat` | Username for registry auth | | `verbose` | no | `true` | Verbose test output | | `report-format` | no | `text` | `text` or `json` | | `skip-tests` | no | — | Comma-separated test IDs to skip (prefix match) | | `skip-pull` | no | `false` | Skip docker pull (image already loaded locally) | ¹ Either `image` **or** both `organization-id` and `project-id` are required. **Output**: `exit-code` — the test runner's exit code. ### The `AUTH_*` forwarding pattern The action forwards every env var that matches `AUTH_*` on its step into the verifier container with `-e AUTH_FOO=...`. You don't have to enumerate them inside `with:` — just set them in the step's `env:` block and they flow through. This is how persona credentials reach the verifier inside the container. ## Versioning The examples above pin to `@main` for simplicity. For production pipelines, pin to a release tag once the actions repo cuts one (recommended convention: `@v1`). ## Troubleshooting **Workflow can't reach the registry / image pull fails** The `DEZYCRO_REGISTRY_TOKEN` secret needs registry-read scope for your organization's namespace. Generate a fresh PAT, paste it in, re-run. **`authenticator '' not configured`** Either the persona's `AUTH_` repo secret is missing/empty, or the persona's `Environment Variable` in the UI doesn't match what the verifier expects. The convention is `AUTH_` uppercased — verify both ends agree. See also the [Personas & Auth troubleshooting](https://docs.dezycro.ai/guides/personas/#troubleshooting) for issues with the auth-config JSON itself. **Tests pass locally but 401 in CI** The `AUTH_` secret value differs from what your local `auth.local.json` resolves to. Common causes: - Secret editor stripped quotes (try base64-encoding). - Secret holds only the token instead of the full auth-config JSON. - The env var was set on the wrong scope (repo vs. environment) and the workflow targets the other scope. **Spec ingest succeeds but Dezycro shows no new endpoints** The upload is async — verifier-binary generation picks up the new document within a few seconds, but UI cache can lag. Hard-refresh the project page. If the endpoints still aren't there, check the document name in the workbook: ingestion is upsert-by-name, so if you renamed the spec file you may have created a *second* document instead of replacing the first. **Secrets leak into logs** They shouldn't — the verifier and the action both log only persona names and env var names. If you see a literal token in a log, [file an issue](mailto:support@dezycro.ai). # Flow Map The **Flow Map** is an interactive visualization of the user flows described in your PRD. Dezycro's AI reads the PRD, extracts the journeys a user can take through the feature and the decision points along the way, and lays them out as a navigable graph. It exists to answer one question before any code is written: *did the AI understand your PRD the way you meant it?* If the graph shows a flow you never intended — or is missing one you did — the PRD is ambiguous, and now is the cheapest moment to fix it. ## Where to find it Open a feature's PRD page and switch the side panel to the **Flow Map** tab (next to Conflicts). Use **Fullscreen** for the full canvas. The same graph also backs the journey/decision summary used elsewhere in the product. ## How it's generated - Generation runs **automatically in the background** once your PRD has enough content. A status indicator shows progress while the graph is being built. - Edited the PRD and want a fresh graph? Hit **Regenerate** in the Flow Map toolbar. - Generation is AI-driven and counts against your [token allowance](https://docs.dezycro.ai/account/billing/#what-counts-toward-your-ai-token-allowance) like other PRD-derived generation. ## What's in the graph The toolbar offers three lenses on the same graph — **Journeys**, **Decisions**, and the full **Flow** canvas — plus a step-through walkthrough player and a complexity score. - **Journeys** — end-to-end paths a user takes through the feature ("create a widget", "fail to delete someone else's widget"). These become the seed for [test journeys](https://docs.dezycro.ai/guides/test-management/index.md). - **Decision points** — places where the flow branches (validation outcomes, permission checks, error paths). - **Gap nodes** — behavior your PRD *implies* but never defines (e.g. "pagination mechanism (undefined)") is surfaced as an explicit gap, so you can fix the PRD before tests are generated from it. - Every node cites the PRD section it came from (§N) — click through to jump to the source passage. ## Why it gates the lifecycle The flow map is the bridge between *documents* and *verification*. When you finalize the PRD (mark it `COMPLETE`), the feature transitions `DRAFT → APPROVED`, the [workbook](https://docs.dezycro.ai/concepts/workbook/index.md) initializes, and the approved flow graph becomes the basis for journey generation and the agent context. This is why [`/dezycro:work`](https://docs.dezycro.ai/claude-code/skills/#dezycrowork-feature) refuses to start a coding session on a `DRAFT` feature: without an approved flow graph there are no journeys, no execution plan, and no agent context — review the graph in the webapp first. ## Review checklist Before finalizing the PRD, scan the flow map for: - [ ] **Missing journeys** — a behavior your PRD promises that has no path in the graph - [ ] **Invented journeys** — a path in the graph your PRD never asked for (ambiguous wording usually causes this) - [ ] **Missing failure branches** — every decision point should have its "no" path; thin error handling here becomes thin negative-test coverage later # Document ingestion (RAG) Upload existing documents — design docs, internal specs, runbooks, customer-facing docs — to ground AI generation in your real product context. Uploaded documents are processed, chunked, embedded, and stored in a vector index that the AI retrieves from during PRD authoring, TRD authoring, and test generation. Note Ingested documents are *read-only grounding material*. For living pages that humans and agents read **and write** day-to-day (runbooks, environment notes, agent lessons), use [Notebooks](https://docs.dezycro.ai/guides/notebooks/index.md) instead. ## Supported formats - PDF - Word documents (`.docx`) - Markdown (`.md`) - Plain text (`.txt`) Max file size: 50 MB. Larger files should be split before upload. ## Uploading 1. Navigate to your project. 1. Open the **Documents** tab → **Upload**. 1. Drop the file. Ingestion runs as a background workflow. Info Processing takes 10–60 seconds depending on file size. Status: `processing` → `ingested` or `failed`. You can navigate away — status is preserved server-side. You can also upload via the MCP server (`mcp__dezycro__upload_document` / `upload_document_content`) if you're scripting bulk ingestion. ## What happens at ingestion time 1. **Parse** — extract text from the source format 1. **Chunk** — split into semantically meaningful pieces (~512 tokens each, with overlap) 1. **Embed** — run each chunk through an embedding model 1. **Index** — write to your project's vector index 1. **Done** — document available for retrieval Embedding calls run on shared infrastructure and do **not** count against your token allowance — see [What does NOT count](https://docs.dezycro.ai/account/billing/#what-does-not-count). ## How retrieved chunks are used When the AI generates a PRD or test case, it issues a **hybrid retrieval** query (dense embeddings + sparse keyword) against your project's vector collection, retrieves the top-K most-relevant chunks, and includes them in the LLM prompt as grounding context. This means generated content: - Cites your actual product terminology, not generic patterns - Reuses your existing user-flow patterns where they apply - Identifies features, user journeys, and acceptance criteria already in your docs - Provides accurate per-feature context without you having to paste anything ## Managing ingested documents The **Documents** tab shows: | Field | Description | | ----------- | ----------------------------------------- | | Name | Document filename | | Status | `processing` / `ingested` / `failed` | | Chunk count | Number of indexed chunks | | Source type | How the doc was uploaded (UI / MCP / API) | | Ingested at | Timestamp | ### Importing as a PRD Click **Import as PRD** on any ingested doc to load it into the PRD editor as an editable starting point. Useful when an existing spec is close to what you want. ### Re-indexing If you edit an ingested doc (re-upload the same filename), Dezycro deletes the old chunks and re-indexes the new content. Vector collection stays consistent. ### Deleting Delete from the Documents tab. Removes the doc + its chunks + any embeddings. Generated PRDs and tests that referenced it stay (the retrieval was at generation time; the output is independent of the source after generation). ## Document-test traceability Every test case generated from a PRD captures the **source chunk references** that grounded it. From the test case detail panel, expand **Sources** to see which document and which paragraph drove the test. This is how you spot coverage gaps: if a critical paragraph in your spec has no test referencing it, that's a missing journey. ## How retrieval works Documents are chunked, embedded, and stored in a per-project vector index. At generation time, retrieval combines semantic and keyword matching, then re-ranks the top candidates to select the most relevant chunks as grounding context. Embedding calls always run on Dezycro's shared infrastructure — they're free of charge and unaffected by [BYOK](https://docs.dezycro.ai/account/auth/#bring-your-own-key-byok-pro-and-above). # Notebooks **Notebooks** are durable, workspace-scoped knowledge surfaces — the place for the operational knowledge that doesn't belong to any single feature: runbooks, SOPs, environment gotchas, research logs, lessons your agents learn the hard way. Where the [knowledge base](https://docs.dezycro.ai/guides/knowledge-base/index.md) holds *uploaded reference documents* that ground AI generation, notebooks are *living pages* that humans and agents read and write during day-to-day work. ## The model - Every workspace has a **default notebook**; you can create more (plan limits below). - A notebook contains **pages** — markdown documents, optionally organized into **directories** (paid plans). - **Humans create and delete notebooks** in the web UI (**Notebooks** in the top bar). **Agents can read and write pages but can never create or delete a notebook** — the container is always under human control. - Every page edit creates a version snapshot server-side. ## Plan limits | | Free | Pro | Team | Enterprise | | ----------------------- | ----- | --------- | --------- | ---------- | | Notebooks per workspace | 1 | 3 | Unlimited | Unlimited | | Pages per notebook | 1 | 15 | Unlimited | Unlimited | | Characters per page | 5,000 | Unlimited | Unlimited | Unlimited | | Directories | — | ✓ | ✓ | ✓ | Limits are enforced server-side regardless of which surface (UI, MCP) does the writing. ## How agents use notebooks Notebooks are designed to be read *efficiently* by agents — a page isn't just a blob of markdown. Via the [MCP server](https://docs.dezycro.ai/api/mcp/#notebooks): 1. **Discover** — `list_notebooks`, then `read_notebook_toc` for a notebook's directories and page titles (no content, cheap). 1. **Search** — `search_notebook` runs section-level semantic search and returns ranked hits, each with a `recommendedView` telling the agent the cheapest way to read that section. 1. **Read** — `read_page` supports structured views, from cheapest to most expensive: `CONTEXT` (orientation), `OVERVIEW` (outline), `SECTIONS`, `PROCEDURE` (ordered steps only), `EVIDENCE`, `PATHS` (decision trees), `GRAPH`, and `MARKDOWN` (full body, last resort). 1. **Write** — `write_page` / `update_page` for free-form markdown, or `write_runbook_page` for structured runbooks: the agent supplies typed fields (summary, prerequisites, steps, commands, validation, rollback) and the server assembles canonical markdown. The structured views are what make notebooks agent-friendly: an agent following a runbook can fetch just the `PROCEDURE` steps instead of re-reading the whole page every turn. ## What belongs in a notebook - **Runbooks** — "how to deploy", "how to run the migration", "how to rotate this credential" - **Environment gotchas** — the local-setup quirks that burn an hour each time someone forgets - **Research logs** — findings worth keeping after the conversation that produced them is gone - **Agent lessons** — corrections you've given an agent that should survive into future sessions Feature-specific knowledge (decisions, issues, assumptions) belongs in the feature's [workbook](https://docs.dezycro.ai/concepts/workbook/index.md), not a notebook. Rule of thumb: if it's about *one feature*, workbook; if it's about *how this team or environment works*, notebook. # OpenAPI Specs Dezycro uses your service's OpenAPI specification as the source of truth for what your API actually does. The richer the spec, the better Dezycro's generated tests, journey plans, and verifier runs. This page covers: 1. Generating an OpenAPI spec from your codebase 1. Getting that spec into Dezycro ## Why Dezycro needs a spec When you run [`/dezycro:publish-spec`](https://docs.dezycro.ai/claude-code/skills/index.md) — or push a spec through the [CI ingest action](https://docs.dezycro.ai/guides/ci-integration/index.md) — Dezycro: - Resolves your declared endpoints, request/response schemas, and auth requirements - Generates **Journey Execution Plans (JEPs)** that string endpoints into realistic user journeys - Drives the **verifier** with assertions tied to your real schema - Improves the relevance of PRD/TRD generation when your spec describes real product behavior, not just CRUD A weak or missing spec degrades all of the above. The cheapest, biggest improvement most teams can make is a complete OpenAPI document. ## Generating a spec You almost never want to write OpenAPI by hand. Pick the generator native to your framework and let it derive the spec from the code that handles requests. Quarkus + SmallRye is what we run internally and what we recommend. We use [SmallRye OpenAPI](https://smallrye.io/docs/smallrye-open-api/) — exposed in Quarkus via the [`quarkus-smallrye-openapi`](https://quarkus.io/guides/openapi-swaggerui) extension — and recommend it. **Add the extension:** pom.xml ``` io.quarkus quarkus-smallrye-openapi ``` Or with Gradle: build.gradle.kts ``` implementation("io.quarkus:quarkus-smallrye-openapi") ``` That's it for the minimum. SmallRye introspects your Jakarta REST (`@Path` / `@GET` / `@POST` / `@Produces` …) endpoints and serves a complete spec at: - `http://localhost:8080/q/openapi` — YAML - `http://localhost:8080/q/openapi?format=json` — JSON **Configure the info block** in `application.properties`: ``` quarkus.smallrye-openapi.info-title=My API quarkus.smallrye-openapi.info-version=1.0.0 quarkus.smallrye-openapi.info-description=Public surface of the Foo service. quarkus.smallrye-openapi.servers=https://api.example.com ``` **Annotate where defaults aren't enough.** Most endpoints don't need any annotations; SmallRye reads the JAX-RS method signature. Add annotations only where you want more detail: ``` @POST @Path("/widgets") @Operation( summary = "Create a widget", description = "Idempotent on the (name, scope) pair." ) @APIResponse(responseCode = "201", description = "Widget created") @APIResponse(responseCode = "409", description = "Widget already exists") public Response create(@Valid CreateWidgetRequest body) { ... } ``` **Verify it locally:** ``` curl http://localhost:8080/q/openapi?format=json | jq '.paths | keys' | head ``` You should see every endpoint your service exposes. **Official docs:** - [SmallRye OpenAPI documentation](https://smallrye.io/docs/smallrye-open-api/) - [`smallrye/smallrye-open-api` on GitHub](https://github.com/smallrye/smallrye-open-api) - [Quarkus — Using OpenAPI and Swagger UI](https://quarkus.io/guides/openapi-swaggerui) Use [springdoc-openapi](https://springdoc.org/). pom.xml ``` org.springdoc springdoc-openapi-starter-webmvc-ui 2.6.0 ``` Spec is served at `/v3/api-docs` (JSON) and `/v3/api-docs.yaml`. **Official docs:** - [springdoc-openapi reference](https://springdoc.org/) - [`springdoc/springdoc-openapi` on GitHub](https://github.com/springdoc/springdoc-openapi) FastAPI generates a spec automatically at `/openapi.json`. No setup needed beyond declaring your routes with type hints and Pydantic models. **Official docs:** - [FastAPI — OpenAPI overview](https://fastapi.tiangolo.com/tutorial/metadata/) - [FastAPI — First steps](https://fastapi.tiangolo.com/tutorial/first-steps/) Use [drf-spectacular](https://drf-spectacular.readthedocs.io/). settings.py ``` INSTALLED_APPS += ["drf_spectacular"] REST_FRAMEWORK = { "DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema", } ``` Spec is served at `/api/schema/` (configurable). **Official docs:** - [drf-spectacular documentation](https://drf-spectacular.readthedocs.io/) - [`tfranzel/drf-spectacular` on GitHub](https://github.com/tfranzel/drf-spectacular) We don't have a single recommendation — both [tsoa](https://tsoa-community.github.io/docs/) (TypeScript, code-first) and [swagger-jsdoc](https://github.com/Surnet/swagger-jsdoc) (JSDoc-driven) work. Whichever you pick, expose the resulting JSON at a stable URL. **Official docs:** - [tsoa documentation](https://tsoa-community.github.io/docs/) · [`lukeautry/tsoa` on GitHub](https://github.com/lukeautry/tsoa) - [`Surnet/swagger-jsdoc` on GitHub](https://github.com/Surnet/swagger-jsdoc) ## Getting the spec into Dezycro Once your service serves a spec, there are two paths into Dezycro depending on who's driving: ### Interactive — `/dezycro:publish-spec` From Claude Code inside the repo: ``` /dezycro:publish-spec ``` This auto-detects the spec endpoint (e.g. `/q/openapi`, `/v3/api-docs`, `/openapi.json`), optionally filters to the active feature's endpoints, uploads to Dezycro, and triggers verifier-binary generation. See the [Claude Code commands reference](https://docs.dezycro.ai/claude-code/skills/#dezycropublish-spec). ### Automated — CI ingest action For backends that publish a new spec on every release, use the [ingest-to-dezycro action](https://docs.dezycro.ai/guides/ci-integration/#ingest-to-dezycro) in your build pipeline with `source-type: OPENAPI`. A full example is in the [CI integration guide](https://docs.dezycro.ai/guides/ci-integration/index.md). ## Spec quality checklist A spec that maximizes what Dezycro can do for you: - [ ] **Every endpoint your service exposes is listed** — including auth, health, admin routes - [ ] **Request and response bodies have schemas**, not free-form `object` - [ ] **Path/query/header parameters declare types and constraints** (`format`, `minimum`, `maxLength`, `enum`) - [ ] **All non-2xx responses are documented** (401, 403, 404, 409, 422, 5xx) - [ ] **Security schemes are declared** (`bearerAuth`, `apiKey`, OAuth flows) and applied per-endpoint - [ ] **`info.title` and `info.version` are meaningful** — Dezycro uses them as labels You don't have to hit all of these on day one. Even a bare-bones auto-generated spec is a big upgrade over no spec at all. # Personas & Auth Dezycro's generated tests run as real users — `admin1`, `user1`, `readonly1`, etc. Each of those identities is a **persona** with its own role, permissions, and credentials. The verifier picks the right persona for each test journey and authenticates as them when calling your API. This guide covers the full path from **defining personas in Dezycro** through **wiring credentials locally** to **passing them to CI**. Configure personas before generating tests Dezycro's test generator decides *which* persona drives each journey at generation time. If your project has no personas (or only `default`), every generated journey runs as an unauthenticated anonymous client — which won't reach any endpoint behind auth and won't exercise role-aware behavior. **Set your personas up first**, then trigger test generation. ## Running example: `widgets-api` We'll thread a concrete example through this guide so every snippet has somewhere real to land. - **Service**: `widgets-api`, a small backend exposing `GET /widgets`, `POST /widgets`, and `DELETE /widgets/{id}`. - **API base URL**: `https://api.acme.example`. - **Auth**: OIDC password-grant token endpoint at `https://auth.acme.example/oauth/v2/token`. Responses look like `{"access_token": "...", "expires_in": 3600}`. - **Three personas** we'll set up: - `admin1` — can create, list, and delete widgets - `user1` — can create and list, but not delete - `readonly1` — can only list (drives negative-case assertions like "POST should 403") If your stack is different (OAuth client credentials, custom dev login, API keys) you'll see in [Auth types](#auth-types) which one to pick instead. ## Creating personas in the app Personas live at **Organization Settings → Test Personas**. Each one defines: - **Name** — must match the persona name your tests reference (e.g. `admin1`, `user1`) - **Description** — what this persona can and can't do (the test generator reads this when assigning personas to journeys) - **Auth type** — how the verifier obtains credentials (see [Auth types](#auth-types) below) - **Scope** — `Tenant` makes the persona usable across all workspaces in the organization; `Workspace` limits it to one workspace - **Environment variable** — the name of the CI secret that will carry this persona's credentials at run time (convention: `AUTH_`) Click **+ Add Persona** to open the create dialog: The **Auth Type** dropdown determines how the verifier gets a token for this persona: ## Auth types The verifier ships with six auth strategies. Pick the one that matches how your service issues tokens. Calls a token endpoint (OAuth2 password grant, OIDC, custom dev login route) once per run, caches the response, and attaches the token to every request. This is what `widgets-api` uses. **Env var contents** for `admin1` (JSON, serialized into the single `AUTH_ADMIN1` env var): ``` { "url": "https://auth.acme.example/oauth/v2/token", "method": "POST", "headers": { "Content-Type": "application/x-www-form-urlencoded" }, "body": "grant_type=password&client_id=widgets-api&username=admin@acme.example&password=hunter2", "tokenPath": "access_token", "headerName": "Authorization", "headerPrefix": "Bearer " } ``` | Field | Default | Notes | | -------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | `url` | — required | Token endpoint | | `method` | `"POST"` | HTTP method (uppercased) | | `headers` | `{}` | Request headers; `"Host"` is honored if you need to override the vhost | | `body` | `""` | Request body — form-encoded or JSON, whatever the endpoint expects | | `tokenPath` | `"access_token"` | **Top-level** JSON field in the response that holds the token. Nested paths (`data.token`) are not supported — the lookup is a flat map access. | | `headerName` | `"Authorization"` | Header to send on subsequent test requests | | `headerPrefix` | `"Bearer "` | Prefix prepended to the token (mind the trailing space) | **Constraints:** - The token endpoint **must return JSON**. Plain-text token responses aren't supported — wrap them in JSON or pick a different auth type. - The field named by `tokenPath` **must be a string** and non-empty. - The request has a fixed **30-second timeout**. - The result is cached per-persona for the lifetime of one verifier run, so the endpoint is called at most once per persona per run. Concurrent journeys for the same persona share one token via singleflight. A static bearer token. Use for long-lived service accounts or pre-minted PATs. If `widgets-api` minted a pre-shared service account token instead of issuing them via OIDC, `admin1` would look like: ``` { "token": "wapi_pat_eyJhbGciOiJI..." } ``` Verifier sends `Authorization: Bearer `. HTTP Basic auth — username + password, base64-encoded into the `Authorization` header. Configuration for a hypothetical Basic-auth `widgets-api`: ``` { "username": "admin@acme.example", "password": "hunter2" } ``` Arbitrary static headers. Use for API keys, signed tokens, or any auth scheme where headers are pre-known and don't need to be exchanged. If `widgets-api` authenticated by API key, `admin1` would carry: ``` { "headers": { "X-Widgets-Api-Key": "ak_live_admin_abc123", "X-Client-Id": "widgets-api" } } ``` The verifier merges these headers into every request. Custom JavaScript for exotic auth (request signing, HMAC, TOTP, MFA). The script is registered with Dezycro server-side and embedded into the verifier binary; the env var just supplies inputs. If `widgets-api` signed requests with HMAC, `admin1` would carry the keying material: ``` { "accessKey": "AKIA_ADMIN_EXAMPLE", "secret": "wJalr_admin_secret_example" } ``` The script receives a filtered `process.env` (`AUTH_*`, `API_*`, `DEZYCRO_*`) plus the JSON above, and must return `{ headers: { ... } }`. No auth headers. Explicit documentation that a persona is deliberately unauthenticated — for testing public endpoints or anonymous-user flows. ``` {} ``` No credentials needed in CI for `NONE` personas. For `widgets-api`, you might add an `anon` persona of type `NONE` to assert "`POST /widgets` should return 401 to anonymous clients." ## Persona design tips - **Cover each distinct authorization tier.** At minimum: one admin, one regular user, one read-only / unauthorized counter-example. The test generator uses your descriptions to decide which persona should hit which endpoint and to write negative-case assertions (e.g. "readonly should 403 on this POST"). - **Be specific in descriptions.** For `widgets-api`, "admin1: can create, list, and delete widgets" is OK. "admin1: can create / list / delete widgets in any workspace; cannot impersonate other organizations; widget bodies must be ≤ 4 KB" is much better — the generator writes both positive and negative tests from this. - **Match names to your auth realm.** If your tests reference `widgets_admin` and `widgets_partner`, name the personas the same. The verifier's persona-resolution is name-based. - **Use `Tenant` scope for shared identities, `Workspace` scope when workspaces have different user pools.** For `widgets-api`, if every workspace shares the same admin/user/readonly identities, all three are `Tenant`-scoped. If each workspace has its own pool, scope them `Workspace`. ## Local development For local `/dezycro:verify` runs, credentials live in `.dezycro/auth.local.json` (gitignored). This file references secrets indirectly so plaintext credentials never enter the repo. `/dezycro:init` creates and maintains it for you. ### `auth.local.json` for `widgets-api` All three personas, with passwords pulled from a local secrets directory: ``` { "version": 1, "personas": { "admin1": { "envVar": "AUTH_ADMIN1", "type": "http_endpoint", "config": { "url": "https://auth.acme.example/oauth/v2/token", "method": "POST", "headers": { "Content-Type": "application/x-www-form-urlencoded" }, "body": "grant_type=password&client_id=${WIDGETS_CLIENT_ID}&username=admin@acme.example&password=${ADMIN_PASSWORD}" } }, "user1": { "envVar": "AUTH_USER1", "type": "http_endpoint", "config": { "url": "https://auth.acme.example/oauth/v2/token", "method": "POST", "headers": { "Content-Type": "application/x-www-form-urlencoded" }, "body": "grant_type=password&client_id=${WIDGETS_CLIENT_ID}&username=user@acme.example&password=${USER_PASSWORD}" } }, "readonly1": { "envVar": "AUTH_READONLY1", "type": "http_endpoint", "config": { "url": "https://auth.acme.example/oauth/v2/token", "method": "POST", "headers": { "Content-Type": "application/x-www-form-urlencoded" }, "body": "grant_type=password&client_id=${WIDGETS_CLIENT_ID}&username=readonly@acme.example&password=${READONLY_PASSWORD}" } } }, "secrets": { "WIDGETS_CLIENT_ID": "!file:~/.dezycro/secrets/widgets_client_id", "ADMIN_PASSWORD": "!file:~/.dezycro/secrets/widgets_admin", "USER_PASSWORD": "!file:~/.dezycro/secrets/widgets_user", "READONLY_PASSWORD": "!cmd:op read op://Private/widgets-api/readonly/password" } } ``` `${NAME}` placeholders inside `personas[].config` are resolved from the `secrets` block before the env var is serialized. Secrets can come from local files, environment variables, or shell commands (1Password, `pass`, etc.) — see the [backend table below](#secret-backends). ### Secret backends Pick whatever you already have: | Backend | Example value | | ---------------------- | ----------------------------------------------------------------- | | Plain file (chmod 600) | `!file:~/.dezycro/secrets/admin1` | | Process env | `!env:ADMIN_PASSWORD` | | 1Password CLI | `!cmd:op read op://Private/MyApp/admin/password` | | `pass` / `gopass` | `!cmd:pass show myapp/admin` | | macOS Keychain | `!cmd:security find-generic-password -a $USER -s myapp-admin -w` | | GCP Secret Manager | `!cmd:gcloud secrets versions access latest --secret=myapp-admin` | For `!cmd:` the shell is `/bin/sh -c`, output is trimmed, and a non-zero exit or empty stdout is treated as an error. ### How `/dezycro:verify` uses it 1. Loads `.dezycro/auth.local.json` 1. Resolves every `secrets[*]` reference (first error aborts) 1. Substitutes `${NAME}` placeholders inside each `personas[*].config` 1. `JSON.stringify`s each resolved config and exports it as the named env var 1. Runs the verifier binary 1. Unsets the env vars when the run finishes — they never land in shell history or parent-process env For the full local flow including `/dezycro:init`'s interactive setup, see the [Claude Code plugin install guide](https://docs.dezycro.ai/claude-code/install/index.md). ## In CI CI uses the same persona definitions and the same auth-config JSON shapes — you just skip the `.dezycro/auth.local.json` indirection and store the pre-resolved JSON directly as CI secrets, one per persona. The [CI Setup guide](https://docs.dezycro.ai/guides/ci-integration/index.md) walks through the full pipeline, including how to wire each persona's secret into the `run-dezycro-tests` step and how to handle per-environment credentials. ## Troubleshooting **`authenticator '' not configured (check AUTH_CONFIG_ env var)`** The verifier couldn't find an env var named by its embedded `AUTH_CONFIG`. Check: - The persona's `Environment Variable` in the UI matches what the verifier expects — convention is `AUTH_` uppercased. - The CI secret (or `auth.local.json` entry) is actually set and non-empty. - For local runs, every `${…}` placeholder in the persona's config resolved (no stale `!file:` path, no missing `!env:` var, no command that returned empty stdout). **`token endpoint returned status 401`** The `http_endpoint` auth call itself failed — wrong client_id, wrong credentials, or wrong grant type for that endpoint. Reproduce with `curl -d '' ''` using the resolved values to confirm. **`token field 'access_token' not found or empty in response`** `tokenPath` doesn't match the response shape. `tokenPath` is a **top-level field name** — nested paths like `data.token` are *not* supported. Inspect the response with `curl` and either use the actual top-level field (common alternatives: `id_token`, `accessToken`, `token`), or, if the token is genuinely nested, change the endpoint's response shape on your side. **Tests pass locally but 401 in CI** The `AUTH_` secret value differs from what `auth.local.json` resolves to. Common causes: secret editor stripped quotes; secret holds the *token* directly instead of the *full auth-config JSON*; the env var was set on the wrong scope (repo vs. environment) and the workflow runs in a different scope. **Secrets leak into logs** They shouldn't — the verifier and `/dezycro:verify` log only persona names and env-var names, never values. The `run-dezycro-tests` action redacts them too. If you see a literal token in a log, [file an issue](mailto:support@dezycro.ai). # Projects, features & documents Projects, features, and the two document types (PRD + TRD) are the unit of work in Dezycro. ## Projects A project is the top-level grouping inside a workspace. Each project contains: - **Features** — the unit of behavior (each with its own PRD/TRD + workbook) - **Ingested Documents** — uploaded files used for RAG enrichment of PRDs and tests - **Settings** — project-scoped defaults The project page surfaces a stat row across the top (features, new, in-progress, complete, tests), the project's folders for grouping related features, and the feature list itself underneath. The **Project ID** copy chip next to the title is the same one [CI Setup](https://docs.dezycro.ai/guides/ci-integration/#finding-your-ids-in-the-app) reads from. ### Project status | Status | Meaning | | ------------ | ----------------------------------------- | | **Active** | Currently being worked on | | **Archived** | No longer active, preserved for reference | Archive / rename / delete projects from the project page or the sidebar context menu. ## Features A **feature** is the smallest planned unit of behavior — typically one user story or one related cluster. Features live inside a project and can be nested under directories for organization. When you create a feature, Dezycro auto-creates two documents (PRD + TRD) and an empty workbook for it. ### Feature lifecycle ``` DRAFT → APPROVED → IN_PROGRESS → VERIFIED → SHIPPED ``` Transitions are mostly automatic — see [The Workbook → Lifecycle stages](https://docs.dezycro.ai/concepts/workbook/#lifecycle-stages). ### Folder-Aware Feature Creation When creating a feature, Dezycro suggests a directory placement based on the feature name + existing project structure (RAG-backed). You can accept the suggestion, override with a different directory, or place the feature at project root. ## The two documents Every feature has two associated markdown documents: ### PRD (Product Requirement Document) Describes **what** should happen — user stories, acceptance criteria, the behavior the user can expect. There's no required schema; structure it the way that fits the feature. The feature stepper at the top of the page (Product Requirements → Technical Requirements → Agent Context → Validation) shows the lifecycle and lets you jump between the four artifacts; the right panel runs continuous conflict detection against other PRDs in the same project, and also hosts the [Flow Map](https://docs.dezycro.ai/guides/flow-map/index.md) — review it before finalizing the PRD. ### TRD (Technical Requirement Document) Describes **how** it'll be built. There's no required format — see the dedicated [TRDs guide](https://docs.dezycro.ai/guides/trds/index.md) for what tends to work well, plus authoring and revision flow. ## Document status Each document moves through: | Status | Meaning | | --------------- | ----------------------------------------------------------------------- | | **DRAFT** | Work in progress | | **IN_PROGRESS** | Actively being authored / revised | | **COMPLETE** | Author considers it done — the "ready" signal the rest of Dezycro reads | You can edit any document at any time; every saved revision is preserved as a version snapshot, so history is never lost. ## Authoring methods Three ways to write each document: 1. **Web UI editor** — direct markdown editing 1. **AI chat** in `app.dezycro.ai` — describe what you want, the AI drafts the document 1. **[`/dezycro:author`](https://docs.dezycro.ai/claude-code/skills/#dezycroauthor-doc-prd-doc-trd-revise-existing)** in the Claude Code plugin — guided state machine: discovery → clarifying Q&A → drafting → quality gate For TRDs specifically, `/dezycro:author --doc trd` is the recommended path — it bakes the quality gate into the loop and won't let you finalize a TRD that doesn't address every PRD pillar. ## Conflict detection When multiple PRDs or PRD sections contain contradictory or overlapping requirements, Dezycro highlights the conflicts. You can: - Review each conflict with the conflicting sections side by side - Dismiss false positives - Resolve by editing the underlying section # Test case generation Dezycro generates test cases from your feature's TRD using **LogicStudio** — an interactive interface for reviewing, toggling, and finalizing AI-generated tests. The output of LogicStudio becomes the feature's **journeys** — see [The Workbook → Journeys](https://docs.dezycro.ai/concepts/workbook/#journeys). ## Opening LogicStudio Navigate to a feature and open the **Validation** tab in the feature stepper. The **Generate Validation Cases** button kicks off LogicStudio's generation workflow. The first time you open this tab for a feature you'll see this empty state; once cases exist they appear as a grid in the same panel. ## Generating test cases 1. Click **Generate** in LogicStudio. 1. The AI analyzes your feature's TRD + any ingested documents. 1. Test cases are generated covering: 1. **Happy paths** — standard user flows 1. **Edge cases** — boundary conditions, unusual inputs 1. **Negative testing** — invalid inputs, unauthorized access, error handling 1. **Integration points** — interactions between features Info Generation runs as a background job and may take 1-3 minutes for a large TRD. A progress indicator shows the current phase. You can navigate away and come back; status is preserved server-side. You can also generate via the [MCP server](https://docs.dezycro.ai/api/mcp/index.md): `mcp__dezycro__generate_tests(workspaceId, projectId, featureId)`, then poll `list_test_cases` until the generated cases appear (the Claude Code plugin instead [blocks on the build event](https://docs.dezycro.ai/api/#waiting-on-events)). ## Reviewing test cases Generated test cases appear in a validation grid. Each test case includes: | Field | Description | | ------------- | ----------------------------------------------- | | Name | A concise description of what the test verifies | | Description | Detailed test scenario and steps | | Linked intent | The TRD/PRD statement this test is grounded in | | Status | Active or Inactive | ## Toggling tests - **Active** — included in verifier runs - **Inactive** — excluded but preserved for later Use **Select All** / **Deselect All** for bulk operations. Toggling is non-destructive — you can re-activate any test at any time. ## Enforcement Each journey has an enforcement state: - **ENFORCED** — failure blocks the feature lifecycle from advancing to VERIFIED - **OBSERVED** — logged but non-blocking (useful for nice-to-have coverage or in-progress journeys) Set via the journey details panel. ## Finalizing When you're satisfied with the test selection, click **Finalize**. This: - Marks the selected tests as Active - Triggers verifier-binary generation - Returns control to the feature page You can also **Continue Later** to come back without finalizing. ## Auto-baselines For spec operations that no generated journey covers, Dezycro synthesizes lightweight **auto-baseline** checks straight from the OpenAPI spec. They give you cheap initial coverage, but they're treated as best-effort — they never reach the highest evidence level on their own. When an auto-baseline matters enough to enforce fully, **promote** it (via `mcp__dezycro__promote_auto_baseline`, or from the journey details panel). Promotion turns it into a regular journey that participates in verifier execution with full enforcement weight. ## Promotion to regression suite Once a feature reaches `VERIFIED` — all enforced journeys passing — you can **promote it to regression** (feature page, or `mcp__dezycro__promote_to_regression`). This: - Transitions the feature `VERIFIED → SHIPPED` - Merges the feature's spec into the project baseline - Recompiles the project's **regression binary**, which covers every SHIPPED feature Pull the regression binary with `mcp__dezycro__pull_regression_binary(projectId, platform)` and run it on every CI build as your "must always pass" gate — same mechanics as the per-feature verifier, project-wide scope. # Verifier runs A **verifier run** is one execution of the verifier binary against your service, recorded against the feature's workbook. Runs are how Dezycro proves a feature actually works — not just that it has tests, but that the tests pass against a real running service. For the full mechanics of how the verifier works, see [The Verifier](https://docs.dezycro.ai/concepts/verifier/index.md). This page covers the workflow once you have a verifier set up. ## Running the verifier Three paths, same result: | Where | How | | ------------------ | ------------------------------------------------------------------------------------------- | | Web UI | Feature page → **Run verifier** button | | Claude Code plugin | [`/dezycro:verify`](https://docs.dezycro.ai/claude-code/skills/#dezycroverify-env-name) | | CI / standalone | [See the CI example](https://docs.dezycro.ai/concepts/verifier/#running-the-verifier-in-ci) | All three upload the result to the same workbook, where it appears in the feature's run history. ## Run results Each run produces a structured result; the workbook rolls per-run outcomes up into a journey status: | Journey status | Meaning | | -------------- | --------------------------------------------------------------- | | **PASSING** | Last run completed end-to-end with all assertions matching | | **FAILING** | Last run hit at least one failed assertion or couldn't complete | | **SKIPPED** | Intentionally excluded — journey is `Inactive` | | **PENDING** | Journey not yet exercised by any run | Non-passing results come with a **verdict** indicating the likely cause — decisive failures (`FAIL_DECISIVE_*`) versus inconclusive runs (`INCONCLUSIVE_*` — missing auth, missing fixture, input constraint). See the [verdict table](https://docs.dezycro.ai/concepts/verifier/#failure-verdicts). ## What advances the lifecycle The feature auto-transitions to `VERIFIED` when: - All **ENFORCED** journeys are `PASSING` - All journey-linked tasks are `CONFIRMED` - No open `HIGH`-severity issues remain - No unresolved coverage gaps with `lifecycleBlocking: true` `OBSERVED` journeys can fail without blocking the lifecycle — useful for in-progress journeys or nice-to-have coverage. ## Run history Every run is preserved. From the feature page, expand any run to see: - Per-journey results - HTTP request/response for each step (when verifier is configured to capture) - Diff against the previous run (which journeys regressed, recovered, or stayed the same) Comparing runs across builds is how you spot regressions before they ship. ## Coverage reports Each run also feeds the feature's **coverage report** — a separate projection that buckets every spec operation by how far it got: bound, executable, observed, inconclusive, decisively failed, or explicitly waived — plus dependency-flow gaps. See [The Verifier → Coverage](https://docs.dezycro.ai/concepts/verifier/#coverage) for the full bucket list. Coverage reports are accessed via the feature page's **Coverage** tab or `mcp__dezycro__get_coverage_report`. The [Claude Code plugin's coverage nudges](https://docs.dezycro.ai/claude-code/companion/#4-coverage-nudges) surface gaps before a push. ## Auth setup Most journeys need authentication. Dezycro models test identities as **personas** loaded from `.dezycro/auth.local.json` — see [Verifier → Personas](https://docs.dezycro.ai/concepts/verifier/#personas-authlocaljson). # TRDs (Technical Requirement Documents) The TRD is the **technical translation of the PRD** — the document that says *how* something will be built. PRDs say what should happen; TRDs say how. Dezycro takes TRDs seriously because journey generation, the verifier binary, and downstream tooling all read from them. A sparse TRD produces sparse coverage. ## What goes in a TRD There's **no required schema or format**. Write a TRD the way that works for your team. The shape that tends to work well covers a few areas — architecture / system shape, data model, API contracts, failure modes, migration / rollout strategy, and open questions — but treat that as a starting point, not a checklist. A short, sharp TRD that addresses what actually matters for your feature beats a long one padded out to fit a template. What does matter: - **The API contracts are concrete enough to drive your OpenAPI spec.** That's what the verifier validates against. - **Failure modes are spelled out.** This is where most negative-test journeys come from. Hand-wave here and the feature ships fragile. - **Open questions are honest.** Every TRD has them; pretending you don't have any is what causes implementation surprises later. ## Authoring a TRD Three paths: ### Web UI editor The plain markdown editor. Useful for small edits or when you have a draft in another tool you want to paste in. ### AI chat Open the TRD document → use the chat panel. Describe what you want; the AI drafts sections using your PRD + ingested documents as grounding. ### `/dezycro:author --doc trd` (Claude Code) Guided state machine: scan existing work → clarify gaps with you → propose placement → create-or-load feature → discovery (gather context) → draft → iterate with you → finalize. State persists to the authoring transcript so the loop survives compaction. For a TRD without an approved PRD, `/dezycro:author --doc trd` refuses by default — the PRD is the input to the TRD authoring, so it has to exist first. ## Revising an approved TRD ``` /dezycro:author --doc trd --revise-existing ``` Loads the current TRD content and walks you through revising it section-by-section. Each section can be kept unchanged, edited in place, or rewritten from scratch. History is preserved — every saved revision creates a new version snapshot. Old versions are read-only but viewable. ## TRD lifecycle ``` DRAFT → IN_PROGRESS → COMPLETE ``` - **DRAFT** — Work in progress. - **IN_PROGRESS** — Actively being authored or revised. - **COMPLETE** — Author considers it done. This is the signal the rest of Dezycro reads — `/dezycro:work` won't start a coding session until both PRD and TRD are `COMPLETE`. Every revision is preserved as a version snapshot, so you can always compare against earlier drafts. For major surgery on a finished TRD, `--revise-existing` is the right tool. ## How TRDs interact with the rest of Dezycro | Surface | What it reads from the TRD | | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | | [LogicStudio](https://docs.dezycro.ai/guides/test-management/index.md) | The endpoint definitions + failure modes — to generate test journeys | | [Verifier](https://docs.dezycro.ai/concepts/verifier/index.md) | Indirectly — via the OpenAPI spec you publish from the TRD | | Coverage projection | The TRD's endpoint inventory — to identify which paths should have journey coverage | | Open questions | Become the seed for [workbook Decisions](https://docs.dezycro.ai/concepts/workbook/#decisions) as questions get resolved | ## Common failure modes - **TRD diverges from the published OpenAPI spec.** Symptom: verifier reports `FAIL_DECISIVE_CONTRACT` on journeys that "should pass." Fix: update one to match the other. - **TRD is comprehensive but the API contracts section is thin.** Other sections aren't load-bearing the way API contracts are — keep them tight. - **`--revise-existing` rewrites too aggressively.** Keep unchanged sections unchanged; the per-section flow exists specifically to keep stable parts stable. ## See also - [The Workbook](https://docs.dezycro.ai/concepts/workbook/index.md) — journeys, tasks, decisions, issues - [`/dezycro:author`](https://docs.dezycro.ai/claude-code/skills/#dezycroauthor-doc-prd-doc-trd-revise-existing) — the guided authoring state machine - [The Verifier](https://docs.dezycro.ai/concepts/verifier/index.md) — what proves the TRD's API contracts are honored # Workspaces A workspace is a container *inside* your tenant. Tenants have one or more workspaces; each workspace has its own projects, features, members, and verifier runs. See [Authentication & access](https://docs.dezycro.ai/account/auth/#tenant-vs-workspace) for the tenant-vs-workspace distinction. ## Creating a workspace From the sidebar workspace switcher, click **Create Workspace** and give it a name. The new workspace starts empty — you become its first **Admin**. Workspace count is plan-dependent: 1 on Free, 5 on Pro, unlimited on Team and Enterprise — see [Billing & plans](https://docs.dezycro.ai/account/billing/#plans). ## Workspace contents Each workspace holds: - **Projects** — top-level groupings of related features - **Features** — the smallest planned unit of behavior (each with PRD + TRD + workbook) - **Members** — users with workspace-level roles - **Verifier runs** — the per-feature verifier history ## Roles Workspace roles are independent — a user can be Admin in one workspace and Viewer in another: | Role | Permissions | Counts as a seat? | | ---------- | -------------------------------------------------------------- | ----------------- | | **Admin** | Full control — manage members, settings, all content | Yes | | **Editor** | Create + edit projects, features, PRDs, TRDs; run the verifier | Yes | | **Viewer** | Read-only access to all workspace content | No | See [Billing & plans → Roles, seats, and what counts](https://docs.dezycro.ai/account/billing/#roles-seats-and-what-counts) for how billable users are defined across workspaces in a tenant. ## Switching workspaces The sidebar workspace switcher shows all workspaces you're a member of (across all tenants you belong to). Your active workspace context is preserved per browser session. In the screenshot above, the **Default Workspace** dropdown at the top of the sidebar is the switcher; below it sits the project tree for whichever workspace is currently active. ## Workspace settings Open **Settings → Workspace** (visible to workspace Admins) to: - Rename or archive the workspace - Invite, remove, or change roles for members - View the workspace activity feed - Configure per-workspace defaults Tenant-level settings (billing, SSO, audit log retention) live under **Settings → Tenant** and are visible only to the Tenant Owner. # Claude Code Plugin # Claude Code Plugin The Dezycro Claude Code plugin brings Dezycro's workbook, verification, and PRD/TRD authoring flows directly into your Claude Code session. Once installed, eight slash commands appear under `/dezycro:*`, and the **Companion** background loop quietly guards the work Claude does for you against silent regressions. ## What you get **Slash commands** for the day-to-day Dezycro flow without leaving your editor: | Command | What it does | | ---------------------------------- | ------------------------------------------------------------------------- | | `/dezycro:init` | Connect a repo to a Dezycro workspace + project | | `/dezycro:work ` | Start or resume work on a feature; binds the session to the workbook | | `/dezycro:author --doc prd \| trd` | Guided PRD/TRD authoring with a built-in quality gate | | `/dezycro:status` | Compact workbook snapshot for the active feature | | `/dezycro:sync` | Sync the current chunk of work to the workbook | | `/dezycro:publish-spec` | Auto-detect + upload an OpenAPI spec; triggers verifier-binary generation | | `/dezycro:verify` | Pull the verifier binary, run it locally, upload results | | `/dezycro:import-features` | Reverse-engineer a codebase into Dezycro features with PRDs + TRDs | **Companion** (V2) — background hooks that: - **Block** tasks from going to DONE / PUSHED without recent passing verifier evidence - **Nudge** you to re-publish your OpenAPI spec when you touch a controller - **Sweep** the workbook for decisions, issues, and assumptions worth recording — only when you ask (e.g. "save progress") or right after a verify - **Surface** coverage gaps before you push Everything is opt-in per-trigger. Companion stays out of your way unless something material happened. ## Next steps - [Install the plugin](https://docs.dezycro.ai/claude-code/install/index.md) — `npm install` or Claude Code plugin install - [Slash commands reference](https://docs.dezycro.ai/claude-code/skills/index.md) - [Companion (V2)](https://docs.dezycro.ai/claude-code/companion/index.md) — what the background loop does + how to tune it # Companion (V2) Companion is the **background loop** layer of the plugin — five small hook handlers that fire on Claude Code events (PreToolUse, PostToolUse, UserPromptSubmit, Stop) and keep the work Claude does for you honest against the workbook. Design principle: Companion is **silent unless something material happened**. If you're mid-implementation and nothing is committed-decision-ish, Companion stays out of your way. When you finish a verify, when you mark a task DONE, when you say "save progress" — those are the moments it speaks up. ## The pillars ### 1. Proactive verify gate Blocks `mcp__dezycro__update_task` calls that try to mark a path-linked task as **DONE** or **PUSHED** when no recent passing verifier run is on file. The agent receives a structured deny with the specific paths and the exact `/dezycro:verify --path

` command to run. **Why:** prevents the most common silent failure — Claude marking work "done" when the verifier would have failed it. **Override:** set `companion.autoVerify.preTaskDone: false` in `.dezycro/config.json`. ### 2. Spec-publish nudge Tracks every `Edit` / `Write` / `MultiEdit` against `companion.autoVerify.controllerPaths` (default: `**/controllers/**`, `**/api/**`). When a controller path is touched, Companion records the change and sets `needsSpecPublish=true`. The next `/dezycro:verify` run reads that flag and **chains `/dezycro:publish-spec` first**, so you never run the verifier against a stale spec. After 5 controller edits without a verify, Companion emits a one-line pulse nudge. ### 3. Workbook sweep — trigger-based, silent by default When the agent finishes a turn, Companion **does nothing by default**. It fires the workbook-sweep directive only when one of these is true: - The user said a wrap phrase on this turn: `save progress`, `log what we did`, `/dezycro:sync`, `wrap up`, `we're done`, `end of session`, etc. - `/dezycro:verify` just completed this turn (snapshot moment for committed decisions). When it does fire, the directive asks the agent to scan the recent conversation for: - **Decisions** (committed technical/product choices) - **Issues** (current blockers/bugs) - **Assumptions** (unverified beliefs) - **Task-status hints** (a tracked task is now DONE/PUSHED) …with confidence thresholds per the configured preset (default `conservative`: 0.85 / 0.80 / 0.90 / 0.90). The agent then calls the matching MCP workbook tool (`add_decision`, `add_issue`, `add_assumption`, `update_task`) and announces what it logged in plain English, with an `'undo that' if wrong` suffix. **Caps:** at most 2 entries per turn, 10 per session (configurable). Content-hash dedup against a 32-entry ring buffer prevents the same decision from being logged twice. **Undo:** type `undo that` on the next user turn (within the immediate-next-turn window) and Companion emits a reversal directive that flips the entry to INVALIDATED / CANCELLED / restores the prior task status. ### 4. Coverage nudges Two nudges, both deterministic — no LLM round-trip: - **Pre-PUSH:** when you mark a task PUSHED and the verifier passed, Companion surfaces a one-liner of remaining coverage gaps via the system-message channel. Never blocks; informational only. - **Post-verify Stop:** if a verify completed after the previous snapshot was last surfaced, Companion emits a coverage **delta** (e.g. `Coverage delta since last verify: -2 paths uncovered, -1 baseline stale`). The one-liner format pluralizes and omits zero-count segments: ``` Coverage: 3 paths uncovered, 1 endpoint not in spec ``` ### 5. `/dezycro:author` sanity check When the agent calls `change_document_status` to mark a TRD **COMPLETE**, Companion runs a light deterministic sanity check against the most-recent draft sidecar — flags obvious placeholder tokens (`TBD`, `TODO`, `FIXME`) and warns on tiny drafts so a half-finished doc doesn't accidentally get marked as done. There's no schema enforcement — TRDs don't have a required structure. The check exists as a "did you mean to do that?" guard, not as a content gate. ## Configuration All settings live in `.dezycro/config.json` under the `companion` key. Defaults (you can override any of these per-repo): ``` { "companion": { "safeMode": false, "autoVerify": { "preTaskDone": true, "prePush": true, "postEditPulse": { "enabled": true, "threshold": 5 }, "autoPublishSpecOnControllerChange": true, "controllerPaths": ["**/controllers/**", "**/api/**"] }, "autoWorkbookUpdates": { "enabled": true, "preset": "conservative", "maxAutoLogsPerTurn": 2, "maxAutoLogsPerSession": 10, "thresholds": { "decision": null, "issue": null, "assumption": null, "taskStatus": null } }, "coverageNudges": { "enabled": true, "staleBaselineDays": 14 } } } ``` ### Confidence presets | Preset | Decision | Issue | Assumption | Task-status | | -------------- | -------- | ----- | ---------- | ----------- | | `conservative` | 0.85 | 0.80 | 0.90 | 0.90 | | `balanced` | 0.75 | 0.70 | 0.80 | 0.85 | | `aggressive` | 0.60 | 0.55 | 0.70 | 0.75 | Numeric `thresholds.*` overrides win over the preset (per-type). ### Kill switch Set `companion.safeMode: true` to disable all Companion behaviors except the deterministic Pillar 1/2 gates. Or disable individual pillars via the per-key `enabled: false` flags. ## State and logs Companion writes two files under `.dezycro/`: - `companion-state.json` — session counters, ring buffers, last verify timestamp, coverage snapshot. Safe to delete (regenerates). - `companion.log` — JSON-lines log of every hook firing. Tail with `tail -f .dezycro/companion.log | jq` to debug. Both files are gitignored by `/dezycro:init`. ## Manual trigger You can also drive Companion's workbook sweep directly: ``` /dezycro:sync ``` Or say "save progress" — the next assistant turn-end will fire the sweep. # Installation The Dezycro plugin adds eight `/dezycro:*` slash commands to your Claude Code session and runs a small background companion that quietly guards your work against silent regressions. This page covers the npm install path. If your Claude Code build supports the plugin marketplace, you can also install through there — see [Plugin marketplace](#plugin-marketplace) below. ## Prerequisites - **[Claude Code](https://claude.com/claude-code)** installed (`claude` on your `PATH`) - **Node.js 18 or newer** — check with `node --version` - **A Dezycro account** — sign up at [app.dezycro.ai](https://app.dezycro.ai). The free tier is enough to try the plugin end-to-end. ## Install ``` npm install -g @dezycro-ai/agent-plugin ``` That's it. The install registers eight slash commands and enables the Companion background hooks. Re-running the command later upgrades you in place — your settings are preserved. Open a new Claude Code session and you should have: ``` /dezycro:init /dezycro:work /dezycro:author /dezycro:status /dezycro:sync /dezycro:publish-spec /dezycro:verify /dezycro:import-features ``` ## Connect to Dezycro The slash commands talk to Dezycro through an MCP (Model Context Protocol) connection. You only do this once: ``` npx dezycro-setup ``` Paste your API key when prompted — you can find it at **Dezycro → Settings → API Keys** (format `dzy_…`). The setup script wires up the MCP connection for you. ## Per-repo setup Inside any repo you want Dezycro to work with: ``` claude # open Claude Code in the repo /dezycro:init # one-time bind of this repo to a workspace + project ``` `/dezycro:init` interactively connects the repo to your workspace and project, detects your dev environment, walks you through persona credentials, and writes `.dezycro/config.json`. Run it once per repo. After that, start working on a feature: ``` /dezycro:work ``` ## Verify the install In a fresh Claude Code session inside a Dezycro-connected repo: ``` /dezycro:status ``` If the command resolves and prints a workbook summary, you're good. If you see "no active feature," that's expected for a first run — just pick one with `/dezycro:work `. ## Updating ``` npm install -g @dezycro-ai/agent-plugin ``` Same command as the original install. Re-running it pulls the latest version and refreshes your local registration. Existing settings are preserved; no manual cleanup needed. ## Uninstalling ``` npm uninstall -g @dezycro-ai/agent-plugin ``` This removes the global package. Your per-repo `.dezycro/` directories are yours — keep them or delete them, nothing global about them. ## Plugin marketplace If your Claude Code build supports plugin discovery, you can install through the marketplace flow instead of npm. The plugin appears under the `dezycro` namespace and registers commands automatically — no `npm install` and no setup steps beyond `/dezycro:init`. ## Troubleshooting ### "Dezycro MCP server is not configured" The plugin is installed but the MCP connection isn't. Run: ``` npx dezycro-setup ``` and paste your API key when prompted. ### Slash commands don't appear Quit Claude Code completely and open a new session — Claude Code only picks up newly registered commands at startup. If they still don't appear, re-run: ``` npm install -g @dezycro-ai/agent-plugin ``` and try again. ### `/dezycro:work` refuses to start on a feature By design. The plugin requires a feature to have a completed PRD, TRD, and approved journey graph before it will load the agent context. Finish the docs in the [Dezycro UI](https://app.dezycro.ai), then re-run. ### `/dezycro:verify` reports a missing authenticator The verifier expects credentials for a persona that the plugin didn't manage to resolve. Re-run `/dezycro:init` — it walks you through persona auth setup. Full details on auth backends are in the [PERSONAS guide](https://app.dezycro.ai/docs/personas). ### Still stuck Email [support@dezycro.ai](mailto:support@dezycro.ai) — include the command you ran and the error you saw. # Slash commands reference All commands are namespaced under `/dezycro:`. Each one is a guided skill — Claude reads the instructions and walks you through the steps interactively. ______________________________________________________________________ ## `/dezycro:init` **Wire a repo to a Dezycro workspace.** Run once per repository. Interactively asks for workspace and project, detects your dev / staging / prod environments, writes `.dezycro/config.json`. ______________________________________________________________________ ## `/dezycro:work ` **Start or resume work on a feature.** Accepts a feature name or UUID. If you don't pass one, the skill helps you pick interactively. Before letting you start, it gates on PRD/TRD/graph approval — features that aren't ready won't unlock until they are. Once accepted, the session is **bound to that feature's workbook**: every Companion action takes the active feature as context. ______________________________________________________________________ ## `/dezycro:author [--doc prd | --doc trd] [--revise-existing]` **Guided PRD or TRD authoring.** V2 flow: discovery → clarifying Q&A → drafting → quality gate → finalize. Built on a state machine that survives compaction — you can step away and come back without losing progress. The TRD quality gate is **deterministic + LLM-reviewed**: a TRD can't be approved until it has all required sections, no placeholder tokens (TBD/TODO/FIXME), and is grounded in the source PRD's pillars. Pass `--revise-existing` to load and edit the current PRD/TRD instead of drafting fresh. ______________________________________________________________________ ## `/dezycro:status` **Compact workbook snapshot for the active feature.** Shows journeys, tasks, recent decisions, open issues, latest verifier results. Requires an active feature (run `/dezycro:work` first). ______________________________________________________________________ ## `/dezycro:sync` **Sync the current chunk of work to the workbook.** Creates tasks for unfinished work, records decisions from the conversation, links commits, flags issues you've discussed. Use it periodically during longer sessions so the workbook reflects reality. Also doubles as the explicit trigger for Companion's workbook sweep — say "save progress" or run this command, and the Stop hook will run a sweep on the next turn-end. ______________________________________________________________________ ## `/dezycro:publish-spec` **Auto-detect + upload an OpenAPI spec for the active feature.** Triggers the verifier build. Run this whenever you've added or changed endpoints — Companion will also nudge you automatically if it detects controller-file edits since the last publish. ______________________________________________________________________ ## `/dezycro:verify [--env ]` **Run the verifier against your local (or remote) environment.** Pulls the latest verifier binary, executes the test journeys, uploads the result run to the workbook. Steps it runs: 1. Check for pending spec publishes (Companion's controller-edit tracker). 1. Pull the verifier binary (cached by content hash). 1. Load auth fixtures from `.dezycro/auth.local.json`. 1. Run the verifier against the configured env's `apiUrl`. 1. Upload the result run via MCP `record_verifier_run`. 1. Surface failing journeys + the top-3 coverage gaps. 1. Update Companion state (`lastVerifyCompletionTs` + `coverageSnapshot`). Step 7 is what arms the post-verify workbook sweep and the pre-PUSH coverage nudge. ______________________________________________________________________ ## `/dezycro:import-features` **Reverse-engineer an existing codebase into Dezycro features.** Scans for product behavior, generates PRDs and TRDs for each detected feature, lets you review and accept. Most useful when onboarding a legacy repo. # Concepts # AI in Dezycro Dezycro uses AI at four key surfaces. All four are grounded in your real product context via RAG over ingested documents. ## 1. PRD authoring The AI chat (web UI) and the [`/dezycro:author --doc prd`](https://docs.dezycro.ai/claude-code/skills/#dezycroauthor-doc-prd-doc-trd-revise-existing) skill (Claude Code) let you create PRDs conversationally. Describe what you want; the AI produces a structured document. Refine via follow-up messages. Output PRD structure: - Overview / user stories / acceptance criteria - **Pillars** — top-level capability groupings (`## Pillar 1: `) that the TRD must subsequently address by name PRDs are not gated — finalize whenever you're happy. ## 2. TRD authoring The TRD is the technical translation of the PRD. Same authoring surfaces (chat + `/dezycro:author --doc trd`). There's no required schema or format — see the [TRDs guide](https://docs.dezycro.ai/guides/trds/index.md) for what tends to work well. On finalize (marking the TRD `COMPLETE`), Companion runs a light sanity check (placeholder tokens like `TBD` / `TODO` / `FIXME`, very-short drafts) — not schema enforcement; just a "did you mean to do that?" guard. ## 3. Test case generation In [LogicStudio](https://docs.dezycro.ai/guides/test-management/index.md), the AI generates test cases (which become **journeys** in the workbook) from the TRD. Coverage targets: - **Happy paths** — standard user flows - **Edge cases** — boundary conditions - **Negative testing** — invalid inputs, auth failures - **Integration points** — interactions between features Each generated journey is grounded in a **linked intent** — the specific TRD/PRD statement it tests. This traceability is what enables coverage reports. ## 4. Workbook sweeps (Claude Code) The [Companion V2](https://docs.dezycro.ai/claude-code/companion/#3-workbook-sweep-trigger-based-silent-by-default) plugin runs an LLM-driven sweep of your recent Claude Code session to extract decisions, issues, assumptions, and task-status hints, and auto-log them to the workbook. Silent by default; triggers on wrap phrases ("save progress", "/dezycro:sync") or after `/dezycro:verify`. ## How RAG works All four surfaces use **retrieval-augmented generation**: 1. Your query/draft becomes an embedding 1. A hybrid (semantic + keyword) search runs against your project's vector index 1. The top candidates are re-ranked for relevance 1. The most relevant chunks are injected into the prompt as grounding context The result: AI output cites your actual product terminology, reuses existing flow patterns, and doesn't invent details that contradict what you've documented. Embedding calls run on shared infrastructure and do not consume your tenant's AI token allowance. ## Model selection By default, all LLM calls go through Anthropic Claude (Opus 4.x family for high-stakes authoring, Sonnet 4.x for chat and lighter generation). Tenants on Pro and above with [BYOK](https://docs.dezycro.ai/account/auth/#bring-your-own-key-byok-pro-and-above) can route to their own provider (Anthropic / OpenAI / Bedrock / Vertex / Azure OpenAI). All tenant-facing calls route through `TenantLlmService`, which resolves the right model + credentials per-tenant transparently. ## Conflict detection When your PRDs (or PRD sections) contain contradictory requirements, the AI flags conflicts with references to the specific contradicting passages. Resolve from the conflict review UI. ## Iterative refinement AI generation isn't one-shot: - Add detail to PRD sections via follow-up chat - Request additional test coverage for specific areas in LogicStudio - Re-run TRD authoring with `--revise-existing` to refine an approved draft Tip The best results combine AI generation with human review and domain expertise. Treat AI output as a strong starting point, not a finished product. The TRD quality gate and [Companion's intent-violation tracking](https://docs.dezycro.ai/concepts/workbook/index.md) are there specifically to catch hallucination drift. # Architecture A high-level map of how Dezycro is structured. For deeper dives, follow the links into the per-area pages. ## Your code stays yours **Dezycro never reads your source code.** There is no repository integration, no code upload, and no server-side code scanning — Dezycro works from your *API surface* and the *artifacts your own agent produces*, never your source. - **Your coding agent reads your code — locally.** When you run `/dezycro:import-features` or `/dezycro:author`, it's *your* Claude Code agent, on *your* machine, reading your files (the access it already has). Dezycro is never in that loop — the agent sends only what it *writes*: PRDs, TRDs, and the workbook. - **`publish-spec` uploads your OpenAPI spec** — your endpoint shapes, not their implementation. - **The verifier runs against your *running* service** over HTTP — it never touches your source files. So what reaches Dezycro is: generated PRDs/TRDs, the workbook, your OpenAPI spec, test journeys, and verifier results. **Your source, your repository, and your secrets never leave your environment.** ## Entity model ``` Tenant (organization) ├── Members (users with tenant-level roles) ├── PATs (Personal Access Tokens) ├── Billing (plan, seats, AI token cap) └── Workspaces └── Projects ├── Ingested Documents (RAG knowledge base) └── Features ← the unit of behavior ├── PRD (product requirements) ├── TRD (technical design) └── Workbook ├── Journeys (test scenarios) ├── Tasks (units of work) ├── Decisions (committed choices) ├── Issues (current blockers) ├── Assumptions (unverified beliefs) └── Verifier runs (execution history) ``` See [Auth & access](https://docs.dezycro.ai/account/auth/#tenant-vs-workspace) for the tenant-vs-workspace distinction, and [The Workbook](https://docs.dezycro.ai/concepts/workbook/index.md) for the inner workbook structure. ## Core workflow ``` Upload Documents ──→ Author Feature ──→ Generate Tests ──→ Run Verifier ──→ Released (RAG) PRD + TRD LogicStudio locally/CI (locked) via AI / chat / /dezycro:author ``` 1. **Upload Documents** — feed existing specs and designs as RAG context. 1. **Author Feature** — create the feature, then write its PRD + TRD via AI chat, the editor, or the [`/dezycro:author`](https://docs.dezycro.ai/claude-code/skills/#dezycroauthor-doc-prd-doc-trd-revise-existing) state machine. 1. **Generate Tests** — open [LogicStudio](https://docs.dezycro.ai/guides/test-management/index.md) to generate journeys from the TRD. 1. **Run Verifier** — the [verifier binary](https://docs.dezycro.ai/concepts/verifier/index.md) is built per-feature from the OpenAPI spec; run it locally or in CI to validate journeys against your real service. 1. **Shipped** — when all enforced journeys pass and the workbook gates are clear, the feature auto-transitions to VERIFIED. Promoting to SHIPPED (the project regression suite) is a deliberate user action. ## The two product surfaces ### Web app — `app.dezycro.ai` - **Mission Control** — landing page; workspace switcher, recent activity, quick links - **AI Chat** — conversational PRD/TRD authoring - **LogicStudio** — test generation + review grid - **Feature page** — workbook tabs (journeys, tasks, decisions, issues, runs, coverage) - **Settings** — tenant (billing, members, SSO, BYOK, audit logs) + workspace (members, defaults) ### Claude Code plugin - 8 `/dezycro:*` slash commands - [Companion V2](https://docs.dezycro.ai/claude-code/companion/index.md) background hooks — verify gate, spec-publish nudge, trigger-based workbook sweep, coverage nudges, TRD quality gate Both surfaces talk to the same backend, the same workbook, and the same verifier. ## Behind the scenes Beyond the two surfaces, a few capabilities are worth knowing about — all reachable through the [MCP server](https://docs.dezycro.ai/api/mcp/index.md) and the Public API: - **Identity & SSO** — standard OIDC. Default login is Google; Enterprise tenants can connect their own identity provider for SSO. Personal Access Tokens authenticate programmatic access (CI, scripts, the plugin). - **Grounded AI authoring** — PRD/TRD authoring and test generation are grounded in the documents *you* upload, via retrieval over your project's knowledge base. See [Document ingestion](https://docs.dezycro.ai/guides/knowledge-base/index.md). - **Test generation** — journeys are generated from your TRD as a background job you can poll for status. - **Verifier pipeline** — Dezycro builds a per-feature verifier binary from your OpenAPI spec, records run results, and computes coverage. The binary runs in *your* environment (local or CI), against *your* running service. - **MCP & Public API** — the same capabilities are available through the [MCP tools](https://docs.dezycro.ai/api/mcp/index.md) and the Public REST API at `api.dezycro.ai/api/v1/...`. ## Data handling Your data is stored encrypted and **isolated per tenant** — every request is scoped to your tenant on the way in. Enterprise tenants can request a **single-tenant deployment** as a paid add-on. Dezycro stores your features, PRDs/TRDs, the workbook, journeys, verifier results, any documents you upload, and your OpenAPI spec. **What it never receives:** your source code, your repository, or your secrets — those stay in your environment; only your own agent reads them, locally (see [Your code stays yours](#your-code-stays-yours)). # The Verifier The Dezycro verifier is a **standalone binary** generated per-feature from the feature's OpenAPI spec + workbook journeys. It runs locally (or in CI) against your service, calls the journey steps, asserts the responses, and uploads a structured result back to the workbook. The verifier is the closing-the-loop step of Dezycro: PRDs/TRDs say what *should* happen, the workbook tracks what was *built*, the verifier proves it *actually works*. ## How a verifier run works 1. **Publish your OpenAPI spec** — via [`/dezycro:publish-spec`](https://docs.dezycro.ai/claude-code/skills/#dezycropublish-spec) or `mcp__dezycro__publish_feature_spec`. This kicks off the verifier build. 1. **Wait for the build** — verifier-binary generation takes ~30–90 seconds. The plugin blocks on the build event (`dezycro await-event --event-types VERIFIER_STATUS_UPDATE`, see [Waiting on events](https://docs.dezycro.ai/api/#waiting-on-events)); outside the plugin, retry `pull_verifier` or watch the feature page. A `FAILED` build can be re-triggered with the `retry_verifier_build` MCP tool. 1. **Pull the binary** — `mcp__dezycro__pull_verifier(featureId, platform)` returns a signed download URL. The Claude Code plugin caches the binary under `.dezycro/bin//dezycro-verify`. 1. **Load auth fixtures** — secrets from `.dezycro/auth.local.json` are resolved into environment variables (one per persona). 1. **Run the binary** — `./dezycro-verify run --all --base-url --json` writes a structured result. 1. **Upload the result** — `mcp__dezycro__record_verifier_run(workspaceId, featureId, results)` posts the run; the workbook updates journey statuses and may auto-transition the feature to `VERIFIED`. The Claude Code plugin's `/dezycro:verify` skill does all six steps in one command. ## Personas & `auth.local.json` Most non-trivial APIs require authentication, and most journeys exercise *multiple* user identities — an admin creating a resource, then a regular user reading it, then a second user trying (and failing) to delete it. Dezycro models these as **personas**. Each persona has: - A `name` (e.g. `admin1`, `customer_a`, `org2_owner`) - An `auth` config — how the verifier obtains a credential for this persona at run time - An `envVar` — the name of the environment variable the verifier reads the credential from ### `auth.local.json` schema The file lives at `.dezycro/auth.local.json` in your repo and is **never committed** (it contains secrets). Schema overview: ``` { "personas": { "admin1": { "envVar": "AUTH_ADMIN1", "auth": { "type": "bearer", "token": "!env:ADMIN_TOKEN" } }, "customer_a": { "envVar": "AUTH_CUSTOMER_A", "auth": { "type": "http_endpoint", "url": "${API_BASE}/auth/login", "method": "POST", "body": { "email": "alice@example.com", "password": "!file:./secrets/alice-pw.txt" }, "extract": "$.access_token" } } } } ``` ### Auth types | Type | Use when | | --------------- | --------------------------------------------------------- | | `bearer` | You have a static token / API key | | `basic` | HTTP Basic auth (`user:pass`) | | `header` | Custom header name + value | | `http_endpoint` | Hit a login endpoint, extract the token from the response | | `js` | Custom JS — for OAuth dances or complex token exchanges | | `none` | Unauthenticated journey | ### Secret backends Secret values support three resolvers: - `!file:` — read the file contents (recommended for tokens in `~/.dezycro/secrets/`) - `!env:` — read an environment variable - `!cmd:` — run a shell command, use stdout (good for `gcloud auth print-access-token` or `aws sts ...`) Substitutions: `${VAR}` anywhere in a string is replaced from the process environment. ### Loading the file The plugin ships `dezycro-resolve-auth` — a binary that reads `.dezycro/auth.local.json`, resolves all secrets, and prints `export KEY='value'` lines for `eval`: ``` eval "$(dezycro-resolve-auth)" ``` The `/dezycro:verify` skill does this automatically. For CI / standalone usage, source it yourself before running the verifier binary. ### Per-persona failures don't block If one persona's secret can't be resolved (e.g. a `!file:` points at a missing file), the resolver prints a stderr warning for that persona and emits nothing for it — other personas still load cleanly. Journeys that need the missing persona return `INCONCLUSIVE_AUTH_REQUIRED` in the verifier output; unrelated journeys still run. ## Verifier output The binary writes JSON with per-journey results: ``` { "metadata": { "specHash": "...", "flowVersion": "...", "jepVersion": "..." }, "journeys": [ { "id": "JOURNEY-1", "name": "Create resource as admin", "status": "pass", "steps": [ /* per-step assertion results */ ] }, { "id": "JOURNEY-2", "name": "Read resource as customer", "status": "fail", "details": "GET /resources/123 returned 200 with shape {...} but spec expected {...}" } ] } ``` Each journey ends `pass`, `fail`, or `skip`. When the run is uploaded, Dezycro classifies every non-passing result with a **verdict** explaining the likely cause — verdicts show up in the workbook and the coverage report. ### Failure verdicts | Verdict | What it means | Fix | | ------------------------------- | --------------------------------------- | ----------------------------------------- | | `FAIL_DECISIVE_ROUTE_MISSING` | Endpoint isn't implemented | Implement it or remove from the spec | | `FAIL_DECISIVE_CONTRACT` | Response shape doesn't match spec | Fix the endpoint or update the spec | | `FAIL_DECISIVE_PERSISTENCE` | State didn't persist | Investigate the write path | | `INCONCLUSIVE_AUTH_REQUIRED` | Persona's credential couldn't be loaded | Add auth fixture for that persona | | `INCONCLUSIVE_SETUP_REQUIRED` | A prerequisite state is missing | Supply parent resource / fixture | | `INCONCLUSIVE_INPUT_CONSTRAINT` | Test input didn't satisfy a constraint | Provide a valid fixture for the parameter | ## Coverage After every run, `get_coverage_report(workspaceId, featureId)` returns a bucketed projection of every operation in your spec: - **`missingBindings`** — operations declared in the spec that no journey could be bound to - **`boundButNotExecutable`** — bound operations that never became runnable (e.g. a setup gap) - **`executableButNotObserved`** — runnable operations that no run actually exercised - **`observedButInconclusive`** — operations that ran but ended in an `INCONCLUSIVE_*` verdict - **`decisiveFailures`** — operations that failed with a `FAIL_DECISIVE_*` verdict (top 3 surfaced by `/dezycro:verify`) - **`waivedManual`** — gaps you explicitly accepted via `waive_coverage` - **`flowGaps`** — dependency-flow gaps between operations; high-confidence gaps block the lifecycle - **`lifecycleBlocking`** — a single boolean: does anything above block the feature from reaching `VERIFIED`? The Claude Code plugin's [coverage nudges](https://docs.dezycro.ai/claude-code/companion/#4-coverage-nudges) read this report to surface gaps before a push. ## Running the verifier in CI The verifier is a single binary, so CI usage is straightforward: ``` - name: Pull verifier run: | curl -fsSL -H "Authorization: Bearer $DEZYCRO_PAT" \ "https://api.dezycro.ai/api/v1/.../verifier" -o dezycro-verify chmod +x dezycro-verify - name: Resolve auth run: | eval "$(npx dezycro-resolve-auth)" echo "AUTH env vars loaded for $(echo $AUTH_* | tr ' ' '\n' | wc -l) personas" - name: Run run: ./dezycro-verify run --all --base-url $API_URL --json > results.json - name: Upload result run: | curl -fsSL -X POST -H "Authorization: Bearer $DEZYCRO_PAT" \ -H "Content-Type: application/json" \ -d @results.json \ "https://api.dezycro.ai/api/v1/.../runs" ``` The Claude Code plugin handles all of this in one command via `/dezycro:verify`; CI is where you'd shell it out yourself. # The Workbook The **workbook** is the working memory of a feature — the structured record of what's been decided, what's pending, what's been verified, and what's still open. PRDs and TRDs describe what *should* happen; the workbook records what's actually happening as the feature gets built. In the feature stepper it's labeled **Agent Context** (third stage, between Technical Requirements and Validation) because that's the role it plays at runtime: every Dezycro-aware AI agent — Claude Code, the [Companion](https://docs.dezycro.ai/claude-code/companion/index.md), the verifier — reads the workbook to ground its next action. When the docs talk about *"the workbook"* or *"the agent context,"* they're the same thing. ## Who writes the workbook Mostly the agent. In a typical Claude-Code-driven session: - **Companion** (background) sweeps the conversation when something material happens and records decisions / issues / assumptions before they get lost. It's [trigger-based and silent by default](https://docs.dezycro.ai/claude-code/companion/#3-workbook-sweep-trigger-based-silent-by-default) — entries land in the workbook without the developer having to step out of flow. - **`/dezycro:sync`** lets the developer say *"checkpoint this"* explicitly — Companion reviews the recent edits, opens the right tasks/issues, and links the commits. - **`/dezycro:verify`** writes journey results, coverage gaps, and run history. - **Test generation** writes journeys and intent links. The human edits the workbook directly only for sharper-than-the-agent-knows nuance: marking an assumption invalidated, raising the severity on an issue, or promoting a journey from `OBSERVED` to `ENFORCED`. This is why the workbook reads less like a doc and more like a database: it's curated by software for software, with human spot-corrections. ## What's in it The workbook surfaces split into eight sub-views in the UI. Each one is a typed log of a different kind of entry: | Sub-view | What lives there | | ------------- | -------------------------------------------------------------------------------- | | **Overview** | A roll-up: open issues, blocking journeys, recent decisions, latest verifier run | | **Journeys** | Generated test journeys + their `ENFORCED` / `OBSERVED` state and last status | | **Tasks** | Discrete units of work an engineer (human or agent) is responsible for | | **Issues** | Bugs, blockers, dev problems with severity and resolution status | | **Decisions** | Committed technical / product choices worth preserving | | **Verify** | Triggers a verifier run and shows the result inline | | **Coverage** | Per-intent / per-endpoint coverage map — what's tested vs what's just speced | | **Audit** | Append-only log of every mutation, with timestamp and actor | ### Journeys A **journey** is a sequence of API calls that exercises a user-facing behavior end-to-end. Generated from the PRD (one journey per user story / acceptance criterion) and the OpenAPI spec, then run by the verifier on demand or in CI. Each journey has: - A name + description - A linked **PRD intent** (the source statement) — used by the coverage report to map "did we test what the PRD promised?" - An ordered list of steps (HTTP calls + assertions) - An **enforcement** state — `ENFORCED` (failure blocks the feature lifecycle from advancing) or `OBSERVED` (logged but non-blocking — useful for nice-to-haves or in-progress journeys) - A **status** — `PENDING` / `PASSING` / `FAILING` / `SKIPPED` ### Tasks A **task** is a unit of work an engineer (human or agent) is responsible for. Each one has: - A status: `PENDING` → `IN_PROGRESS` → `DONE` → `PUSHED` → `CONFIRMED` (forward-only; a task that turns out wrong is marked `INVALIDATED` rather than deleted) - Optional `pathRefs` — files in the codebase the task touches. The [Companion verify gate](https://docs.dezycro.ai/claude-code/companion/#1-proactive-verify-gate) uses these to block transitions to `DONE` or `PUSHED` without recent passing verifier evidence. - Optional links to journeys, decisions, or issues Tasks describe *work*. They're the smallest planning unit. ### Decisions A **decision** is a committed technical or product choice worth preserving: > *"We chose cursor-based pagination over offset for the activity feed."* Decisions have a summary, a rationale, and optional refs back to the journeys / intents they affect. They stay forever — they aren't "completed." If a decision turns out wrong, mark it `INVALIDATED` instead of deleting; the audit trail matters more than tidiness. ### Issues An **issue** is a current problem — a bug, a blocker, a flake — with a severity (`HIGH` / `MEDIUM` / `LOW`) and a forward-only status (`OPEN` → `RESOLVED` → `PUSHED` → `CLOSED`). **Issue vs task**: an *issue* describes the problem; a *task* describes the work to fix it. Most fixes get both — one issue plus one task that links to it. The issue is what the verifier and coverage report read; the task is what shows up on someone's plate. ### Assumptions An **assumption** is a working belief that affects implementation but isn't verified: > *"We're assuming the upstream API returns ISO-8601 timestamps."* Recording assumptions explicitly is what stops them from silently becoming bugs. When an assumption turns out wrong, mark it `INVALIDATED` and (usually) open a corresponding issue. Companion logs assumptions whenever the developer says *"I think…"* / *"I'm pretty sure…"* / *"this should be the case"* in a way that affects code paths. ### Blockers & required paths Some features can't be fully verified until something external is in place — a Stripe webhook subscribed, an OAuth callback configured, a third-party fixture loaded. Record these as **HIGH-severity issues**: explicit prerequisites that must be satisfied before the verifier can run end-to-end. A feature with open `HIGH`-severity issues can't auto-advance to `VERIFIED`, even if all its journeys pass — the agent knows it isn't actually proven. ## Lifecycle stages Each feature progresses through stages, driven by the workbook's contents: ``` DRAFT → APPROVED → IN_PROGRESS → VERIFIED → SHIPPED ↓ ↑↓ ABANDONED IN_PROGRESS (auto-revert) ``` | Stage | Meaning | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **DRAFT** | PRD/TRD being written; flow graph not yet approved; workbook empty | | **APPROVED** | The [flow graph](https://docs.dezycro.ai/guides/flow-map/index.md) has been approved — journeys exist and the workbook is initialized; coding can start | | **IN_PROGRESS** | Implementation underway; some journeys may pass, tasks moving | | **VERIFIED** | All `ENFORCED` journeys are `PASSING`, no open `HIGH`-severity issues, all journey-linked tasks are `CONFIRMED`, and the coverage report has no blocking gaps | | **SHIPPED** | Promoted to the project's regression suite; terminal | | **ABANDONED** | Work intentionally parked; can be re-opened back to `APPROVED` | Transitions are **automatic** where possible. `DRAFT → APPROVED` happens when you approve the flow graph. As soon as the verifier reports all enforced journeys passing — with the issue, task, and coverage gates also clear — the feature auto-moves to `VERIFIED` (and auto-reverts to `IN_PROGRESS` if any gate stops holding). `SHIPPED` is the only deliberate promotion: it merges the feature into the project's regression suite (see [Promotion to regression](https://docs.dezycro.ai/guides/test-management/#promotion-to-regression-suite)). If you want to know *why* a feature is stuck on a stage, the Overview sub-view tells you exactly which gate hasn't been satisfied. ## Documents on a feature Each feature also carries two human-readable documents alongside the workbook: | Type | Purpose | | ------- | ------------------------------------------------------------------------------------------------------------------ | | **PRD** | Product Requirement Document — user stories, acceptance criteria, pillars | | **TRD** | Technical Requirement Document — architecture, data model, API contracts, failure modes, migration, open questions | All three (PRD + TRD + workbook) are auto-created when you call `create_feature`. The documents start in `DRAFT` and the [authoring flow](https://docs.dezycro.ai/claude-code/skills/#dezycroauthor-doc-prd-doc-trd-revise-existing) walks them through `IN_PROGRESS` to `COMPLETE`. Every saved revision is kept as a version snapshot — old versions stay viewable. ## How agents use the workbook This is the part that most differentiates Dezycro from a doc tool: the workbook is **structured exactly so that an agent can ground itself in seconds.** When `/dezycro:work ` starts a session, the plugin loads the entire workbook (overview + open issues + recent decisions + journeys + last verifier run) into the agent's context. The agent then reads: - the PRD to learn *what should happen,* - the TRD to learn *how it's built,* - the **workbook** to learn *what's already been decided, what's broken right now, and what's been verified so far.* That last category is what makes the difference between an agent that hallucinates and an agent that progresses. The PRD/TRD are aspirational; the workbook is current truth. When the agent then *does* work — implements something, runs the verifier, hits a snag — it writes back: - Decisions it made (via `add_decision`) - Issues it found (via `add_issue`) - Assumptions it relied on (via `add_assumption`) - Tasks it completed (via `update_task`) Either explicitly (the developer typed `/dezycro:sync`) or implicitly (Companion noticed something worth recording). ## Editing the workbook Three ways, all writing to the same store: 1. **Web UI** — `app.dezycro.ai` → feature page → workbook sub-views. Canonical surface; every other path's mutations appear here in real time. 1. **MCP** — `add_decision`, `add_issue`, `add_assumption`, `update_task`, `create_task`, `link_artifact`, etc. (see [MCP server](https://docs.dezycro.ai/api/mcp/index.md)). 1. **Claude Code plugin** — Companion auto-logs during a session; `/dezycro:sync` does the explicit checkpoint; `/dezycro:verify` writes run results. (See [Companion](https://docs.dezycro.ai/claude-code/companion/index.md) and [slash commands](https://docs.dezycro.ai/claude-code/skills/index.md).) All three paths share the same audit log — the **Audit** sub-view shows every mutation with timestamp and actor (which user / which agent / which automation). ## What the workbook is for The workbook exists because PRDs and TRDs alone aren't enough to verify a feature is correctly built. A PRD says *what* should happen; the workbook records *what was decided, what was assumed, what was actually tested, and what's still open.* It's also what makes Dezycro safe to leave an agent unattended on. Because every mutation is logged, every assumption is explicit, and every gate to `VERIFIED` is mechanical, you can audit *what the agent did* after the fact — and you can tell whether it actually finished or just *thinks* it did. The verifier consumes the workbook (specifically the journeys + their enforcement state + their linked intents) to produce a coverage report. Coverage gaps surface in the workbook itself — which means the next person (or agent) to work on the feature sees the current truth, not a stale spec. # API & Integrations # API & integrations Dezycro exposes its functionality two ways: | | [MCP server](https://docs.dezycro.ai/api/mcp/index.md) | Public REST API | | ------------- | ------------------------------------------------------ | ------------------------------------------- | | **For** | AI clients (Claude Code, Cursor, custom MCP clients) | Programmatic access from any HTTP client | | **Transport** | Streamable HTTP (MCP protocol) | Standard JSON over HTTPS | | **Endpoint** | `https://mcp.dezycro.ai/mcp` | `https://api.dezycro.ai/api/v1/...` | | **Auth** | `Authorization: Bearer dzy_...` (PAT) | `Authorization: Bearer dzy_...` (PAT) | | **Best for** | Conversational tooling, agent workflows | CI scripts, custom integrations, dashboards | Both surfaces are backed by the same services and the same permission model — your [PAT's](https://docs.dezycro.ai/account/auth/#personal-access-tokens-pats) workspace roles apply equally. ## Quick start ### MCP ``` claude mcp add dezycro \ --transport http \ --url https://mcp.dezycro.ai/mcp \ --header "Authorization: Bearer dzy_..." ``` See the [MCP server reference](https://docs.dezycro.ai/api/mcp/index.md). ### REST ``` curl -H "Authorization: Bearer dzy_..." \ https://api.dezycro.ai/api/v1/workspaces ``` OpenAPI spec is available under the **PUBLIC** tag at `https://api.dezycro.ai/v3/api-docs` — import into Postman / Insomnia or feed to `openapi-generator` for any major language. ## Auth PATs are bearer tokens prefixed with `dzy_`. Create one from **Settings → Personal Access Tokens** in the web app. Pass on every request: ``` Authorization: Bearer dzy_ ``` PATs inherit your workspace role on each call. Tenant-level operations (member management, billing) require Tenant Owner. Full details: [Authentication & access](https://docs.dezycro.ai/account/auth/index.md). ## Rate limits Requests are rate-limited per user, by operation type: | Operation | Limit / minute | | -------------------------------------------- | -------------- | | Reads (`GET`) | 100 | | Writes (`POST` / `PUT` / `PATCH` / `DELETE`) | 30 | | Search | 20 | On top of the per-user limits, a tenant-wide aggregate cap of **1,000 requests / minute** applies across all users in your organization. 429 responses include a `Retry-After` header. MCP returns rate-limit failures as MCP error responses with `code: -32603`. ## Waiting on events Long-running operations (verifier-binary builds, test generation) complete asynchronously. Instead of busy-polling, the [Claude Code plugin](https://docs.dezycro.ai/claude-code/index.md) ships a small CLI that long-polls Dezycro's event inbox and returns the moment a matching event lands: ``` dezycro await-event --event-types VERIFIER_STATUS_UPDATE --feature --timeout 600 ``` Exit codes: `0` — event received (printed as JSON on stdout), `5` — timeout, `2` — error. `/dezycro:verify` and `/dezycro:publish-spec` use this under the hood, so you rarely need to call it yourself. For scripted REST usage, poll the relevant `list_*` endpoint (e.g. `list_test_cases` after triggering generation) with a backoff. ## SDKs No official SDKs yet. The MCP server's tool schemas auto-generate client signatures in MCP-compatible IDEs (Claude Code, Cursor). For REST, generate a client from the OpenAPI spec. # MCP server Dezycro exposes a Model Context Protocol (MCP) server at `https://mcp.dezycro.ai/mcp`. The MCP server is what the [Claude Code plugin](https://docs.dezycro.ai/claude-code/index.md) talks to — but you can also use it directly from any MCP-compatible client (Cursor, Continue, custom IDE plugins, etc.). ## Authentication Use a [Personal Access Token](https://docs.dezycro.ai/account/auth/#personal-access-tokens-pats): ``` Authorization: Bearer dzy_ ``` Pass the header on every request. The MCP server resolves the PAT to your user + tenant + per-workspace permissions on each call — there's no separate workspace selection step. ## Wiring up a client ### Claude Code ``` claude mcp add dezycro \ --transport http \ --url https://mcp.dezycro.ai/mcp \ --header "Authorization: Bearer dzy_..." ``` Or place this in `~/.claude/settings.json`: ``` { "mcpServers": { "dezycro": { "type": "http", "url": "https://mcp.dezycro.ai/mcp", "headers": { "Authorization": "Bearer dzy_..." } } } } ``` ### Other clients Most MCP-compatible clients accept the same shape — point at `https://mcp.dezycro.ai/mcp` and pass the bearer header. The transport is **Streamable HTTP** (the modern MCP transport — initialize handshake, session ID, JSON-RPC over POST). ## Available tools The MCP server exposes the same tools the Claude Code plugin uses. Group-by-purpose: ### Discovery - `list_workspaces` — your accessible workspaces - `list_projects(workspaceId)` — projects in a workspace - `create_project(workspaceId, name)` — new project - `list_features(workspaceId, projectId, parentDirectoryId?)` — directory tree of features - `search(workspaceId, projectId, query)` — semantic search across PRDs, TRDs, and ingested documents - `search_features(workspaceId, projectId, query)` — feature-name search - `list_feature_documents(workspaceId, featureId)` — PRD/TRD docs for a feature - `get_document(workspaceId, featureId, docId)` — fetch document content - `get_workbook(workspaceId, featureId)` — full workbook state (journeys, tasks, decisions, issues, …) ### Feature lifecycle - `create_feature(workspaceId, projectId, placement, name, …)` — new feature; auto-creates PRD/TRD docs - `create_directory(workspaceId, projectId, name, placement)` / `move_directory(...)` — organize features into folders - `move_feature(featureId, targetDirectoryId)` - `update_document(workspaceId, featureId, docId, content)` — overwrite PRD/TRD markdown - `upload_document_content(...)` + `finalize_document_upload(...)` — signed-URL path for documents over 50 KB - `change_document_status(docId, status)` — DRAFT → IN_PROGRESS → COMPLETE transitions - `suggest_placement(workspaceId, projectId, name)` — RAG-backed directory suggestion ### Knowledge base - `upload_document(workspaceId, projectId, name)` — signed-URL upload of a reference document for [RAG ingestion](https://docs.dezycro.ai/guides/knowledge-base/index.md) ### Workbook - `add_decision(workspaceId, featureId, summary, reason, intentRefs?, journeyRefs?)` - `add_issue(workspaceId, featureId, summary, severity, …)` — severity HIGH / MEDIUM / LOW - `add_assumption(workspaceId, featureId, summary, intentRefs?)` - `update_issue(issueId, status, …)` — OPEN → RESOLVED → PUSHED → CLOSED (forward-only) - `create_task(workspaceId, featureId, …)` - `update_task(taskId, status, evidence?, pushRef?)` — PENDING → IN_PROGRESS → DONE → PUSHED → CONFIRMED (forward-only) - `confirm_journey(workspaceId, featureId, journeyId)` / `unenforce_journey(...)` ### Verification & coverage - `publish_feature_spec(workspaceId, featureId, openApiFragment, …)` — upload OpenAPI; triggers verifier-binary generation - `pull_verifier(workspaceId, featureId, platform?)` — signed download URL for the verifier binary - `retry_verifier_build(workspaceId, featureId)` — re-trigger compilation after a failed build - `record_verifier_run(workspaceId, featureId, results, …)` — upload a run result - `get_coverage_report(workspaceId, featureId)` — current coverage projection (see [coverage buckets](https://docs.dezycro.ai/concepts/verifier/#coverage)) - `waive_coverage(workspaceId, featureId, operationId, reason)` — explicitly accept a gap for one `METHOD /path` operation - `pull_regression_binary(projectId, platform?)` — the project-wide regression binary covering all SHIPPED features ### Test generation - `generate_tests(workspaceId, projectId, featureId)` — kick off test generation (async — poll `list_test_cases`, or let the plugin wait on the build event) - `list_test_cases(workspaceId, projectId, status?)` - `promote_auto_baseline(workspaceId, featureId, jepId, operationId)` — upgrade a spec-derived auto-baseline to a full journey - `promote_to_regression(workspaceId, featureId)` — VERIFIED → SHIPPED + regression-suite aggregation - `get_violation_events(workspaceId, eventType, from, to)` — agent intent-violation log ### Notebooks - `list_notebooks(workspaceId)` — workspace [notebooks](https://docs.dezycro.ai/guides/notebooks/index.md) (default notebook first) - `read_notebook_toc(workspaceId, notebookId)` — directories + page titles, no content - `read_page(workspaceId, notebookId, pageId, view?, sectionId?)` — structured views from cheap to full: CONTEXT, OVERVIEW, SECTIONS, PROCEDURE, EVIDENCE, PATHS, GRAPH, MARKDOWN - `search_notebook(workspaceId, notebookId, query, …)` — section-level semantic search; hits include a `recommendedView` for the follow-up read - `write_page(workspaceId, notebookId, title, content?)` — create a page - `update_page(workspaceId, notebookId, pageId, content)` — replace a page's markdown body - `write_runbook_page(workspaceId, notebookId, title, steps, …)` — structured runbook authoring (server assembles the markdown) ### Council (AI review) - `trigger_council_review(workspaceId, featureId, codeDiff?)` — request multi-persona AI review of PRD/TRD - `get_council_review(workspaceId, featureId, …)` — fetch the latest review ### Audit & metrics - `link_artifact(...)` — link a commit / PR / document URL to a workbook entity - `get_workspace_metrics(workspaceId, periodStart, periodEnd)` — blocked-false-completion rate over a date range - `get_avoided_cost_estimate(workspaceId, periodStart, periodEnd)` — estimated dollar value of intent violations caught Each tool's full parameter schema is loaded by your MCP client at connection time — refer to the client's tool browser for the canonical signatures. ## Quirks - **Streamable HTTP transport** — the first POST must be an `initialize` JSON-RPC call; the server returns a `Mcp-Session-Id` header. Subsequent calls must echo that header back. Standard MCP clients handle this automatically. - **Per-workspace permission inheritance** — your PAT inherits your workspace role on every call. A Viewer PAT can call `get_*` / `list_*` tools but not `create_*` / `update_*` ones. - **Idempotency** — `update_document` overwrites; `add_*` always creates a new entity. There's no append semantics on documents. - **Long-running operations** — `generate_tests` and `publish_feature_spec` return immediately; generation and verifier-binary compilation continue in the background. Poll `list_test_cases` / `pull_verifier`, or use the plugin's [`dezycro await-event`](https://docs.dezycro.ai/api/#waiting-on-events) CLI to block until the build event lands.