# Meshery Schemas - Coding Agent Instructions

This is the central schema repository for the Meshery platform. Schemas here drive Go struct generation, TypeScript type generation, and RTK Query client generation. Mistakes in schema design propagate into generated code across multiple downstream repos (meshery/meshery, layer5io/meshery-cloud).

> **This file is a routing and policy overview.** The critical rules - the
> dual-schema pattern, casing, and generated-artifact warnings - live inline
> below. Long-form reference material lives in `docs/` and is linked from the
> [Detailed references](#detailed-references) section. Keep this file concise:
> Claude Code warns when it exceeds 40k characters.
>
> `CLAUDE.md` is a symlink to this file. Edit `AGENTS.md` only.

## Source of Truth

The source of truth for a construct's API contract depends on where it is in the migration lifecycle:

1. **Pre-migration** - While a construct is being migrated from a downstream repository (e.g., `layer5io/meshery-cloud`) into meshery/schemas, the downstream implementation is the reference for field discovery: field names, types, JSON tags, and database column mappings.
2. **Post-migration** - Once a construct has been fully migrated and its schema is defined here, **meshery/schemas becomes the permanent, authoritative source of truth.** Downstream repositories must conform to the contract defined here, not the reverse.

For constructs that have been migrated:

- When a downstream repository's implementation diverges from the schema contract defined here, **this repository is correct** and the downstream code must be updated.
- When cross-construct consistency requires a change that conflicts with current downstream implementation, make the breaking change here and open issues in affected repositories documenting the required migration.
- Do not weaken schema contracts, skip validation rules, or introduce inconsistent patterns to accommodate legacy downstream code.

## Build

```bash
make build       # generate Go structs + TypeScript types + RTK clients
make validate-schemas  # run repository schema validation rules
npm run build    # build TypeScript distribution (dist/)
```

Generated artifacts (`models/`, `typescript/generated/`) are committed by automation on `master`. The TypeScript distribution in `dist/` is produced by the npm build/publish workflow and is not committed to this repo. Do not edit generated artifacts by hand, and do not manually commit regenerated output in normal PRs unless the change explicitly requires it.

**Never hand-edit generated output:**

- ❌ Generated Go code in `models/`
- ❌ Generated TypeScript in `typescript/generated/`
- ❌ Built files in `dist/`

## Required on Every PR

- **Tests accompany every behavioral change.** Run every locally-runnable test
  before requesting review; never defer runnable coverage to reviewers or
  follow-up PRs.
- **Documentation accompanies every behavioral change, in both forms:**
  - External, user-facing: docs.meshery.io and the published OpenAPI documentation - update whenever the change is
    user-visible.
  - Internal, developer-facing: this repo's [`docs/`](docs/) - update whenever
    architecture, workflows, or contracts change.
- **Schema-aware changes**: run `make validate-schemas && make consumer-audit` before pushing.
- **Sign off every commit** (`git commit -s`).
- **No AI attribution** in commits, PR descriptions, comments, or code.

Always run `make build`, `go test ./...`, and `npm run build` before committing schema changes. See [Common Mistakes](docs/schema-review-checklist.md#common-mistakes-to-avoid) and the [Checklist for Schema Changes](docs/schema-review-checklist.md#checklist-for-schema-changes) for the full pre-PR list.

## AXI Agent Tooling

- Use the `gh-axi` CLI tool to interact with GitHub. Prefer `gh-axi` over `gh`.
- Use `chrome-devtools-axi` for browser automation (navigate, snapshot, click, fill forms, run JS, inspect console/network) in place of raw Playwright/chrome-devtools MCP for ad hoc tasks.
- Run `quota-axi` to check local agent-provider quota windows before long-running work.
- Use the `lavish` skill (`lavish-axi` CLI) to turn a plan, comparison, or report into a reviewable HTML artifact.

### Where skills live

`.agents/skills/` is the single source of truth for this repo's agent skills. `.claude/skills` is a
relative symlink to it - add, edit, and remove skills under `.agents/skills/` only, and never replace
that symlink with a real directory. Codex and OpenCode read `.agents/skills` natively, so no
`.codex/skills` or `.opencode/skills` link is needed.

## The Dual-Schema Pattern (REQUIRED)

This is the most critical design rule in this repo. Every agent or contributor MUST follow it.

### Rule 1: `<construct>.yaml` = response schema only

The YAML file for an entity represents the **full server-side object** as returned in API responses. It is NOT a request body schema.

**Required properties of every entity `.yaml`:**

- `additionalProperties: false` at the top level
- All server-generated fields defined in `properties`: `id`, `created_at`, `updated_at`, `deleted_at`
- Server-generated fields that are always present belong in `required`

### Rule 2: Every writable entity needs a `*Payload` schema in `api.yml`

For any entity that has `POST` or `PUT` operations, define a `{Construct}Payload` schema in `api.yml` that:

- Contains **only client-settable fields** - no `created_at`, `updated_at`, `deleted_at`
- Makes `id` optional with `json:"id,omitempty"` for upsert patterns
- Is the schema referenced by all `requestBody` entries for `POST`/`PUT`

### Rule 3: POST/PUT requestBody MUST reference `*Payload`, never the entity schema

Referencing the full entity schema in a `requestBody` is WRONG - it forces clients to supply server-generated fields. Reference the `{Construct}Payload` schema instead.

Worked YAML examples for all three rules (entity schema, payload schema, WRONG vs CORRECT requestBody) live in [Dual-schema pattern examples](docs/schema-authoring-reference.md#dual-schema-pattern-examples).

### Canonical reference implementations

When uncertain, model new schemas on these:

- `schemas/constructs/v1beta1/connection/` - `connection.yaml` + `ConnectionPayload` in `api.yml`
- `schemas/constructs/v1beta1/key/` - `key.yaml` + `KeyPayload` in `api.yml`
- `schemas/constructs/v1beta1/team/` - `team.yaml` + `teamPayload`/`teamUpdatePayload` in `api.yml`
- `schemas/constructs/v1beta1/environment/` - `environment.yaml` + `environmentPayload` in `api.yml`

## Checklist for new entity schemas

Before opening a PR that adds an entity schema, walk the "(New entity)" and "(New endpoint)" items in the
[Checklist for Schema Changes](docs/schema-review-checklist.md#checklist-for-schema-changes).

## Casing rules at a glance

(The ecosystem's identifier naming conventions. Downstream repos cite this section as `meshery/schemas/AGENTS.md § Casing rules at a glance` - do not rename it.)

> **Casing is the single most error-prone area.** The full authority - the
> per-layer casing table and its compatibility caveats - lives in
> [`docs/casing-rules.md`](docs/casing-rules.md). The reader-friendly
> cross-repo directory (26-row before/after table) is in
> [`docs/identifier-naming-contributor-guide.md`](docs/identifier-naming-contributor-guide.md)
> (canonical URL: <https://github.com/meshery/schemas/blob/master/docs/identifier-naming-contributor-guide.md>).

**Wire is camelCase everywhere; DB is snake_case; Go fields follow Go idiom; the ORM layer is the sole translation boundary.**

This repo IS the authority for that contract. The contract is not optional; deviations block PRs via the schemas consumer-audit CI gate. On any conflict, schemas wins - downstream repos file discrepancies as issues against `meshery/schemas`, not locally.

- Property names: for **newly authored API versions**, use **camelCase on the wire, uniformly.** New schema properties and their JSON tags use `camelCase`. For DB-backed fields, the `x-oapi-codegen-extra-tags.db` tag carries the snake_case DB column name separately from the wire identifier. For an already-published API version that publishes `snake_case` on the wire, additions to that same version must preserve the version's published wire casing until the resource is version-bumped; do not perform partial casing migrations within a version.
- ID-suffix fields: `lowerCamelCase` + `Id` (`modelId`, `registrantId`)
- `Id` (camelCase), never `ID`, in URL params, JSON tags, and TypeScript properties.
- New enum values: lowercase words (`enabled`, `ignored`, `duplicate`); preserve published enum literals as-is within the same API version
- Object names: singular nouns (`model`, `component`, `design`)
- `components/schemas` names: PascalCase nouns (`Model`, `Component`, `KeychainPayload`)
- Files/folders: lowercase (`api.yml`, `keychain.yaml`, `templates/keychain_template.json`)
- Endpoint paths: kebab-case, plural nouns, and the `/api` prefix that the authenticated API surface is served under (`/api/workspaces`, `/api/environments`). The declared path must **equal the route the server serves** - nothing prepends `/api` at build time, so a path that does not match ships a client that 404s at runtime without failing any build or validation step. Carry `/api` only where the router group actually applies it: `/user/schedules` is registered on the bare router and is correct without it. Verify against the consumer's route registration (Echo groups supply the prefix); see [`docs/http-api-design.md`](docs/http-api-design.md#declared-paths-are-absolute---there-is-no-implicit-api-prefix).
- Path params: camelCase with `Id` suffix (`{subscriptionId}`, `{connectionId}`, `{orgId}` - NOT `{orgID}`, NOT `{org_id}`)
- `operationId`: lower camelCase verbNoun (`createKeychain`, `updateEnvironment` - NOT `CreateKeychain`, NOT `UpdateEnvironment`)

**Partial casing migrations are forbidden.** Do not recase selected fields within a published API version. If the wire format must change, introduce a new API version and migrate the resource consistently there. See [`docs/casing-rules.md`](docs/casing-rules.md).

## File structure for a construct

Every construct directory `schemas/constructs/<version>/<construct>/` holds `api.yml` (OpenAPI spec: endpoints + all schema definitions), `<construct>.yaml` (entity/response schema), `templates/` (example instances), and optional `forms/` (RJSF form schemas). Full layout: [File structure for a construct](docs/schema-authoring-reference.md#file-structure-for-a-construct).

Auto-generated Go structs live in `models/<version>/<construct>/<construct>.go` (**do not edit**); manual helpers in `<construct>_helper.go` (SQL driver, `Entity` interface, `TableName()`). See [Go helper files](docs/schema-authoring-reference.md#go-helper-files).

## x-internal annotation

**Required on every operation.** The bundler and validate-schemas Rule 14 reject operations that omit it:

- `x-internal: ["cloud"]` - cloud-only (`_openapi_build/cloud_openapi.yml`)
- `x-internal: ["meshery"]` - Meshery-only (`_openapi_build/meshery_openapi.yml`)
- `x-internal: ["cloud", "meshery"]` - both bundled outputs

## Release Procedure

**Use the `meshery-schemas-release` skill** (`/meshery-schemas-release`) to cut releases - it automates the entire procedure and includes safeguards.
**CRITICAL: Do not manually create releases** - no `gh release create`, no manual `npm publish`, no hand-edited release notes, no manual version bumps.
The chain: push to `master` -> `generate-artifacts-from-schemas.yml` self-commits generated artifacts -> `release-drafter.yml` refreshes the draft release -> a human publishes the draft -> publish workflows fan out (`publish-schemas.yml`, npm publish, downstream notifications, OpenAPI docs).
Full procedure, the What NOT to Do list, and versioning policy: [`docs/release-procedure.md`](docs/release-procedure.md). Skill usage and troubleshooting: [`docs/release-procedure-skill.md`](docs/release-procedure-skill.md).

## Detailed references

Long-form reference material lives in `docs/` to keep this file concise. Consult these when you need the full detail:

- **[`docs/casing-rules.md`](docs/casing-rules.md)** - the authoritative per-layer casing table (DB / Go / wire / URL / operationId / TS) and its compatibility caveats.
- **[`docs/identifier-naming-contributor-guide.md`](docs/identifier-naming-contributor-guide.md)** - reader-friendly cross-repo naming directory with before/after examples.
- **[`docs/http-api-design.md`](docs/http-api-design.md)** - HTTP method semantics, response codes, bulk-delete-via-POST, resource grouping, path structure.
- **[`docs/schema-authoring-reference.md`](docs/schema-authoring-reference.md)** - dual-schema worked examples, per-property validation rules (37-42), `x-id-format: external`, RJSF form schemas + enforcement tests, Go helper files, `x-internal`, SQL driver (`Scan`/`Value`) rules.
- **[`docs/schema-review-checklist.md`](docs/schema-review-checklist.md)** - intentional design decisions (do not flag), the 26 common mistakes, and the full pre-PR schema-change checklist.
- **[`docs/schema-tooling.md`](docs/schema-tooling.md)** - identifier-naming migration status, advisory baseline, consumer audit tooling and CI behavior.
- **[`docs/superseded-construct-consumer-verification.md`](docs/superseded-construct-consumer-verification.md)** - how to prove no downstream consumer is still on an `x-superseded-by` construct version; why import-path grepping is invalid on the TypeScript/RTK surface.
- **[`docs/release-procedure.md`](docs/release-procedure.md)** - full release flow, What NOT to Do, and versioning policy.
- **[`docs/release-procedure-skill.md`](docs/release-procedure-skill.md)** - using the `meshery-schemas-release` skill, verification commands, troubleshooting.
- **[`docs/relationship-evaluation-engine-contract.md`](docs/relationship-evaluation-engine-contract.md)** - the authoritative relationship-evaluation wire contract for downstream evaluators.

## Questions?

If you're unsure about any schema modification:

1. Check existing schemas for patterns (e.g., `environment.yaml`, `connection.yaml`)
2. Look at `schemas/constructs/v1alpha1/core/api.yml` for available core schema definitions
3. Examine any construct's `api.yml` to see how subschemas are referenced and endpoints are defined
4. Check generated `.d.ts` files for actual type/property names
5. Review this document and the linked `docs/` references for guidelines
6. Test your changes with `make build` before committing

## Maintaining this file

Keep this file for knowledge useful to almost every future agent session in this project.
Do not repeat what the codebase already shows; point to the authoritative file or command instead.
Prefer rewriting or pruning existing entries over appending new ones.
When updating this file, preserve this bar for all agents and keep entries concise.
