{"_id":"@api-common/spectral-ruleset-studio","_rev":"3-7bdbee8008b778cd2d57a64e8a1499d1","name":"@api-common/spectral-ruleset-studio","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"@api-common/spectral-ruleset-studio","version":"0.1.0","keywords":["spectral","openapi","asyncapi","api-governance","ruleset","linting","style-guide","grounding","api-commons"],"author":{"url":"https://apievangelist.com","name":"API Evangelist"},"license":"Apache-2.0","_id":"@api-common/spectral-ruleset-studio@0.1.0","maintainers":[{"name":"api-commons","email":"info@apicommons.org"}],"homepage":"https://studio.apicommons.org","bugs":{"url":"https://github.com/api-commons/spectral-ruleset-studio/issues"},"bin":{"spectral-ruleset-studio":"bin/cli.js"},"dist":{"shasum":"b0ffb59845da9abaaa9ce69a56f096f3c6b65305","tarball":"https://registry.npmjs.org/@api-common/spectral-ruleset-studio/-/spectral-ruleset-studio-0.1.0.tgz","fileCount":8,"integrity":"sha512-ihzvtNdECZl3jBhWJcgQUA1PaA4i9L+U7meCPgMBOl8kwWe2gmOQXNA8uHzXOmtA7LBvELW/MV8ke0T+FmlLUg==","signatures":[{"sig":"MEUCIQDQk2rcN0io8o+DPDjuHC9NCZFJsGJJunk9HIRXCtKCYgIgaTQJIaHvCObJKzylSlSR5KNNx/topMy9ur3QY0xEv4U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":71398},"type":"module","engines":{"node":">=18"},"exports":{".":"./src/emit-ruleset.js","./catalog":"./src/catalog.js","./templates":"./src/templates.js"},"gitHead":"693887ee59d68449e32bbb392d7d6d0c08ebc948","scripts":{"cli":"node bin/cli.js","dev":"vite","test":"node --test","build":"vite build","preview":"vite preview","build:site":"vite build"},"_npmUser":{"name":"api-commons","email":"info@apicommons.org"},"repository":{"url":"git+https://github.com/api-commons/spectral-ruleset-studio.git","type":"git"},"_npmVersion":"11.6.2","description":"Turn a prose style guide into an OWNED, GROUNDED, well-named Spectral ruleset in your browser — pick a target, one of the 9 core functions, write the message and severity, and ground every rule with an owner, rationale and docs link. An API Commons tool.","directories":{},"_nodeVersion":"25.2.1","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.4.11","typescript":"^5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/spectral-ruleset-studio_0.1.0_1783113463709_0.8822492433016422","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@api-common/spectral-ruleset-studio","version":"0.2.0","keywords":["spectral","openapi","asyncapi","api-governance","ruleset","linting","style-guide","grounding","api-commons"],"author":{"url":"https://apievangelist.com","name":"API Evangelist"},"license":"Apache-2.0","_id":"@api-common/spectral-ruleset-studio@0.2.0","maintainers":[{"name":"api-commons","email":"info@apicommons.org"}],"homepage":"https://studio.apicommons.org","bugs":{"url":"https://github.com/api-commons/spectral-ruleset-studio/issues"},"bin":{"spectral-ruleset-studio":"bin/cli.js"},"dist":{"shasum":"8057115a15640e94df320a92638df0b67a43ae41","tarball":"https://registry.npmjs.org/@api-common/spectral-ruleset-studio/-/spectral-ruleset-studio-0.2.0.tgz","fileCount":8,"integrity":"sha512-WKpuG+z6VTWyGZ/mu0LFZvpBkYCVBi/kvrB9ZG2dvMa6Q/Nb+/zXEpTnk+iOUyBytYXTdWsjWuZamlTGIifDmg==","signatures":[{"sig":"MEYCIQDw6OwItlGhFtR9uo8wM3KaLAWxNOsYgle7E/8E9enC6QIhAKVSaM/yYNUGvAaoCLU9vOU3If5gUfNgY07V8FvDCmm6","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":89050},"type":"module","engines":{"node":">=18"},"exports":{".":"./src/emit-ruleset.js","./catalog":"./src/catalog.js","./templates":"./src/templates.js"},"gitHead":"7d30683693e53d6f983063e9dbefdfe61938cfe5","scripts":{"cli":"node bin/cli.js","dev":"vite","test":"node --test","build":"vite build","preview":"vite preview","build:site":"vite build"},"_npmUser":{"name":"api-commons","email":"info@apicommons.org"},"repository":{"url":"git+https://github.com/api-commons/spectral-ruleset-studio.git","type":"git"},"_npmVersion":"11.6.2","description":"Turn a prose style guide into an OWNED, GROUNDED, well-named Spectral ruleset in your browser — pick a target, one of the 9 core functions, write the message and severity, and ground every rule with an owner, rationale and docs link. An API Commons tool.","directories":{},"_nodeVersion":"25.2.1","dependencies":{"js-yaml":"^4.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.4.11","typescript":"^5.7.2"},"_npmOperationalInternal":{"tmp":"tmp/spectral-ruleset-studio_0.2.0_1783117821369_0.3181502569017822","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@api-common/spectral-ruleset-studio","version":"0.3.0","description":"Turn a prose style guide into an OWNED, GROUNDED, well-named Spectral ruleset in your browser — pick a target, one of the 9 core functions, write the message and severity, and ground every rule with an owner, rationale and docs link. An API Commons tool.","type":"module","license":"Apache-2.0","author":{"name":"API Evangelist","url":"https://apievangelist.com"},"homepage":"https://studio.apicommons.org","repository":{"type":"git","url":"git+https://github.com/api-commons/spectral-ruleset-studio.git"},"bugs":{"url":"https://github.com/api-commons/spectral-ruleset-studio/issues"},"keywords":["spectral","openapi","asyncapi","api-governance","ruleset","linting","style-guide","grounding","api-commons"],"bin":{"spectral-ruleset-studio":"bin/cli.js"},"exports":{".":"./src/emit-ruleset.js","./catalog":"./src/catalog.js","./templates":"./src/templates.js"},"engines":{"node":">=18"},"scripts":{"test":"node --test","dev":"vite","build:site":"vite build","build":"vite build","preview":"vite preview","cli":"node bin/cli.js"},"dependencies":{"js-yaml":"^4.1.0"},"devDependencies":{"typescript":"^5.7.2","vite":"^5.4.11"},"publishConfig":{"access":"public"},"gitHead":"d6f2ef6e956aeac0c078da8fd775509ccbf27507","_id":"@api-common/spectral-ruleset-studio@0.3.0","_nodeVersion":"25.2.1","_npmVersion":"11.6.2","dist":{"integrity":"sha512-Y34kCzO7YMMCT3jJxz95J6BYz/noutpeT+mx8+TiEa/MnsvZP0xoeO6wAYuOZ1/MGgDuFyvP5y2GVqdxpNUoaA==","shasum":"91eaf1fd25b1ed8abc79e5c61a5c974b265953f7","tarball":"https://registry.npmjs.org/@api-common/spectral-ruleset-studio/-/spectral-ruleset-studio-0.3.0.tgz","fileCount":8,"unpackedSize":95126,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDx3ZHEwOaEHxqQ3+9nsqdax6gdiz5NTkkbnfiRdUMBhAIhAOq+jLbpF1In+/jeC8jG0ievAIEC8hPch5VUifeUfeGB"}]},"_npmUser":{"name":"api-commons","email":"info@apicommons.org"},"directories":{},"maintainers":[{"name":"api-commons","email":"info@apicommons.org"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/spectral-ruleset-studio_0.3.0_1783127661556_0.4005224523703357"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-03T21:17:43.581Z","modified":"2026-07-04T01:14:21.819Z","0.1.0":"2026-07-03T21:17:43.853Z","0.2.0":"2026-07-03T22:30:21.494Z","0.3.0":"2026-07-04T01:14:21.692Z"},"bugs":{"url":"https://github.com/api-commons/spectral-ruleset-studio/issues"},"author":{"name":"API Evangelist","url":"https://apievangelist.com"},"license":"Apache-2.0","homepage":"https://studio.apicommons.org","keywords":["spectral","openapi","asyncapi","api-governance","ruleset","linting","style-guide","grounding","api-commons"],"repository":{"type":"git","url":"git+https://github.com/api-commons/spectral-ruleset-studio.git"},"description":"Turn a prose style guide into an OWNED, GROUNDED, well-named Spectral ruleset in your browser — pick a target, one of the 9 core functions, write the message and severity, and ground every rule with an owner, rationale and docs link. An API Commons tool.","maintainers":[{"name":"api-commons","email":"info@apicommons.org"}],"readme":"# Spectral Ruleset Studio\n\n**Turn a prose style guide into an OWNED, GROUNDED, well-named Spectral ruleset — in your browser.**\n\n[studio.apicommons.org](https://studio.apicommons.org) · an [API Commons](https://apicommons.org) tool · free and open under Apache-2.0\n\n---\n\n## Why this exists\n\nIn a census of 1,005 public GitHub pipelines running [Spectral](https://github.com/stoplightio/spectral)\n([The State of Spectral in API Pipelines](https://apievangelist.com)), **63% ran the tool on its\ndefaults with no rules of their own.** The default ruleset is a config file that ships with the\nsoftware — a hodgepodge of atomic checks with no naming convention, no categories, and no owner.\nRunning it is not adopting a standard; it is leaving the settings where you found them.\n\nThe reason teams do this is simple: **authoring and owning rules is hard.** So this tool makes the\nhard part cheap.\n\n> A ruleset you did not write is a ruleset nobody at your organization had to think through, which\n> means it is a ruleset nobody owns — and the identical YAML that is a governance artifact in one\n> repository is an empty gesture in another. The file can be byte-for-byte the same. The difference\n> is entirely whether human work exists behind it.\n\nSpectral Ruleset Studio forces that human work, and makes it fast:\n\n- **Distilling prose is the point.** Paste a line from your style guide — *\"operations should have\n  meaningful descriptions\"* — and the act of turning it into a rule immediately exposes how vague the\n  prose was. Meaningful how? Longer than what? On which operations? The tool flags the vague words\n  and makes you answer. Answering **is** governance happening.\n- **Owned & named.** Every rule gets a convention-following id — the canonical API Commons\n  **Spec / Version / Property / Semantics / Severity** pattern\n  (`<spec>-<version>-<property>-<semantics>-<severity>`, e.g. `oas-x-operation-summary-truthy-warn`) —\n  and a named owner. No anonymous copied YAML. See [the id convention](#the-rule-id-convention).\n- **Grounded.** No rule ships without a description, a rationale (*why*), and a docs/policy link — so\n  a red build is a teachable moment instead of a cryptic roadblock.\n- **Sparingly enforced.** New rules default to `warning`, not `error`. `error` — the build-failing\n  severity — is a deliberate choice you make, because credibility comes from a small blocking set.\n- **Positive or negative framing.** Write the rule that flags what is wrong, or its twin that\n  recognizes what is right, so you can report progress (*\"82% already comply\"*) and not only deficits.\n- **Swagger 2.0 and OpenAPI 3.x, with parity.** Every rule targets both specs. Where the two dialects\n  diverge (`definitions` vs `components.schemas`, `securityDefinitions` vs `components.securitySchemes`,\n  `host`/`schemes` vs `servers`), the tool emits the right JSONPath for each — as a single multipath\n  `given` when the check is identical, or as format-tagged twin rules when it differs.\n\n## What it does\n\n1. **The studio.** Add rules three ways — paste prose to distill, drop in a grounded starter, or start\n   blank — then tune every field:\n   - a **target** (JSONPath `given`) from a library of common ones (operations, parameters, responses,\n     schemas, info, security, naming, servers/tags);\n   - one of the **9 core Spectral functions** — `defined`, `truthy`, `falsy`, `undefined`, `pattern`,\n     `casing`, `length`, `enumeration`, `alphabetical`, `schema` — with guided arguments, **no custom\n     JavaScript required**;\n   - a **message** and a **severity**;\n   - the **required grounding**: id, description, why, docs link, owner (plus optional\n     who/what/when/where).\n2. **A starter library** of ready, already-grounded rule templates you can add and tune —\n   operationId present, descriptions non-empty, consistent error schema, declared security, kebab-case\n   paths, camelCase properties, tags present, and more.\n3. **Live output.** A valid, categorized `.spectral.yaml` that updates as you type, with a \"valid\n   YAML\" indicator, a **Target** toggle (OpenAPI 3.x / Swagger 2.0 / Both), a copy button, and a\n   download button. Every rule carries its grounding.\n4. **A tiny CLI** (`@api-common/spectral-ruleset-studio`) that scaffolds a grounded starter ruleset\n   from the same templates, for wiring into a repo or CI from the terminal.\n\n## How grounding is carried\n\nEvery emitted rule carries its grounding **two ways**, so the output is both portable and\nmachine-readable:\n\n- **In the rule `description`** — a human-readable `Grounding —` block (source statement, why,\n  framing, owner, docs, and any who/what/when/where). This is plain Spectral and works in every\n  version.\n- **Mirrored as an `x-grounding` extension** per rule (toggle off with `--no-ext` or the checkbox) for\n  tooling that wants it structured.\n\nEach rule also sets `documentationUrl` to its docs link. The emitted rulesets lint cleanly under\nSpectral 6.\n\n## The rule-id convention\n\nEvery id the studio emits (and validates on hand-authored rules) follows one canonical convention —\nthe API Commons standard **Spec / Version / Property / Semantics / Severity**, the convention set out\nin the *[A Naming Convention for Your Governance Rules](https://apievangelist.com)* chapter of\n*Governance of APIs*:\n\n```\n<spec>-<version>-<property>-<semantics>-<severity>\n  oas       3          info-title          length      warn\n```\n\n- **spec** — the specification family: `oas` · `aas` · `arazzo` · `jsonschema`.\n- **version** — the spec version as a bare token: `3` (OpenAPI 3.x), `2` (Swagger 2.0), or `x` when a\n  rule is version-agnostic. Spec + version together are exactly Spectral's own format token\n  (`oas3` / `oas2`).\n- **property** — the root/nested property the rule targets, from the JSONPath `given` (+ `then.field`):\n  one or more tokens, e.g. `info-description`, `operation-summary`, `schema-property`, `path`.\n- **semantics** — *what* is checked, from the Spectral function: `defined`, `truthy`, `falsy`,\n  `undefined`, `pattern`, `casing`, `length`, `enumeration`, `alphabetical`, `schema`.\n- **severity** — `error` · `warn` · `info` · `hint`, carried in the name **and** mirrored by the\n  rule's own `severity`.\n\nRead `oas-3-info-title-length-warn` and you know, without opening the rule, that it is an OpenAPI 3.x\nrule on `info.title` enforcing a length at warning severity. Format twins stamp the version segment\n(`oas-3-…` / `oas-2-…`) rather than appending a suffix. The companion\n[governance-pipeline](https://github.com/api-commons/governance-pipeline) (`<org>-…`) and\n[spectral-owasp-ruleset](https://github.com/api-commons/spectral-owasp-ruleset) (`owasp-api<N>-…`)\nids are domain-scoped variants of this same shape.\n\n## Swagger 2.0 / OpenAPI 3.x parity\n\nSpectral auto-detects a document's format (`swagger: \"2.0\"` → `oas2`; `openapi: 3.x` → `oas3`) and\nonly runs a rule on a document whose format is in the rule's `formats` (or on every document when the\nrule declares none). Spectral Ruleset Studio is **format-aware**, so the rulesets you build apply to\nboth specs. A **Target** toggle in the studio output bar (and `--target` on the CLI) chooses which\ndialect(s) to govern:\n\n- **Both** (default) — one ruleset that governs Swagger 2.0 **and** OpenAPI 3.x. Divergent targets are\n  emitted in one of two ways:\n  - a **multipath `given`** — `given: [$.components.schemas.*, $.definitions.*]`, no `formats` tag —\n    when the same check is valid on both paths (e.g. \"every schema property must be described\"). One\n    clean rule, no duplication;\n  - **format-tagged twins** — `<id>-oas3` (`formats: [oas3]`) and `<id>-oas2` (`formats: [oas2]`) —\n    when the check itself differs (e.g. a base URL is `servers[].url` in 3.x but `host` in 2.0).\n  Concepts that exist in only one spec (3.x `requestBody`, 2.0 `host`/`formData`) are tagged\n  `formats: [oas3]` / `[oas2]` so they never mis-fire on the other.\n- **OpenAPI 3.x** / **Swagger 2.0** — emit only that dialect's form of each rule, with a matching\n  top-level `formats`. One-spec-only rules are dropped when they don't apply.\n\nUnder the hood, each divergent target and template records **both** its `oas3` and `oas2` JSONPath\nform; the emitter decides multipath-vs-twin from whether the two forms share the same `then.field`.\n\n## Use it\n\n### In the browser\n\nOpen **[studio.apicommons.org](https://studio.apicommons.org)**, paste your style-guide statements,\nand build. Nothing leaves your browser.\n\n### From the CLI\n\n```bash\n# Emit the whole grounded starter library to stdout\nnpx @api-common/spectral-ruleset-studio\n\n# Only certain areas, written to a file\nnpx @api-common/spectral-ruleset-studio operations info -o .spectral.yaml\n\n# A specific rule by id\nnpx @api-common/spectral-ruleset-studio --id oas-x-operation-operationId-defined-error\n\n# List every template id\nnpx @api-common/spectral-ruleset-studio --list\n\n# A Swagger 2.0-only ruleset (or --target oas3 for 3.x only; default is both)\nnpx @api-common/spectral-ruleset-studio --target oas2 -o .spectral.yaml\n\n# Leaner output (grounding stays in the description, no x- extensions)\nnpx @api-common/spectral-ruleset-studio --no-ext -o .spectral.yaml\n```\n\n**Areas:** `info` · `operations` · `parameters` · `responses` · `schemas` · `security` · `naming` ·\n`servers`\n\n### Then run it (sparingly, and never silently)\n\n```yaml\n- name: Govern the API\n  run: npx @stoplight/spectral-cli lint openapi.yaml --ruleset .spectral.yaml\n```\n\nTurn the findings into something a team will read with the companion\n[Spectral Reporter](https://reporter.apicommons.org).\n\n## Develop\n\n```bash\nnpm install\nnpm run dev      # the studio on a local Vite server\nnpm test         # emitter tests (node --test)\nnpm run build    # build the static site to dist/\nnpm run cli --   # run the CLI locally, e.g. npm run cli -- --list\n```\n\nThe emitter (`src/emit-ruleset.js`), the catalog (`src/catalog.js`) and the templates\n(`src/templates.js`) are pure, dependency-light ESM modules shared **verbatim** between the browser\nSPA and the CLI — so the YAML you copy from the page is byte-for-byte what the terminal writes.\n\n## The 9 functions, and what they check\n\n| Function | Checks |\n| --- | --- |\n| `defined` | the value is present |\n| `truthy` | present and truthy (non-empty) |\n| `falsy` | absent or falsy |\n| `undefined` | not present |\n| `pattern` | matches / does not match a regex |\n| `casing` | follows a casing style (camel, pascal, kebab, snake, …) |\n| `length` | within a min/max length |\n| `enumeration` | one of an allowed set of values |\n| `alphabetical` | keys are in order |\n| `schema` | validates against a JSON Schema |\n\n## Part of the API Commons toolbox\n\n[API Validator](https://validator.apicommons.org) ·\n[Spectral Reporter](https://reporter.apicommons.org) ·\n[API Discovery](https://discover.apicommons.org) ·\n[API Documentation](https://documentation.apicommons.org) ·\n[API Reusability](https://reusability.apicommons.org) ·\n[MCP Install](https://install.apicommons.org)\n\nOpen source and free to fork. When you want experts in the loop, API Evangelist offers\n[governance services](https://apievangelist.com/services/) — writing and grounding an owned ruleset\nagainst your operations, tuning severity and rollout, and wiring it into the pipeline as a gate that\ninforms rather than punishes.\n\n---\n\n© 2026 API Commons (Kin Lane). Licensed under Apache-2.0.\n","readmeFilename":"README.md"}