oc-api-dev — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited oc-api-dev (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
On first invocation, read `references/orchestrator.md` and follow its welcome protocol.
Tri-agent first-party API harness: Designer authors the contract (OpenAPI / GraphQL schema) → Builder scaffolds typed handlers, validation, and an SDK against it → Conformance hits the running server, validates responses against the spec, and diffs the new spec against the previously-shipped one to flag undeclared breaking changes.
This is the producer-side counterpart to oc-integrations-engineer. If you're consuming someone else's API (Stripe, Slack, Salesforce, OAuth providers), use oc-integrations-engineer. If you're designing/building the API your own clients, customers, or partners consume, use this skill.
API DEVELOPER COMMANDS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
TRI-AGENT HARNESS
/oc-api design Author the API contract (Designer agent)
/oc-api build Scaffold + conformance loop (Builder → Conformance)
/oc-api test Run Conformance against an existing server
AUTHOR
/oc-api spec Generate / update OpenAPI or GraphQL schema from data model
/oc-api scaffold Generate typed handlers + validation middleware from spec
/oc-api lint Run spectral / redocly lint on the spec
LIFECYCLE
/oc-api version Plan a new version (URL or header strategy)
/oc-api deprecate Mark endpoints deprecated; emit Sunset/Deprecation headers
/oc-api docs Render human-readable docs from the spec
/oc-api sdk Generate TypeScript / Python / Go SDK from the spec
UTILITIES
/oc-api list Show all endpoints with version + deprecation status
/oc-api drift Compare spec to running code; report mismatches
/checkpoint Show checkpoint status
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Type any command to begin. /oc-api to see this again.API DESIGN INTENT
(from oc-app-architect 02-architecture.md API Design section)
│
▼
┌──────────────────┐
│ API │ Authors contract: OpenAPI / GraphQL schema.
│ DESIGNER │ Decides versioning, pagination, error envelope,
│ │ idempotency, rate-limit policy declarations.
└────────┬─────────┘
│
▼
┌──────────────────────────────────────────────┐
│ BUILD LOOP (per API surface) │
│ │
│ ┌────────────┐ contract ┌─────────────┐ │
│ │ API │◄─negotiate──►│ API │ │
│ │ BUILDER │ │ CONFORMANCE │ │
│ │ │──code──────►│ │ │
│ │ Scaffolds │ │ Hits live │ │
│ │ handlers │◄──failures──│ server + │ │
│ │ + SDK │ │ diffs spec │ │
│ └────────────┘ └─────────────┘ │
│ │ │ │
│ │ All checks pass? │ │
│ └───────────────────────────┘ │
└──────────────────────────────────────────────┘
│
└──► Drift monitoring (ongoing)the code, they "agree" because nothing forces disagreement. In practice handlers drift from OpenAPI within hours: a field gets renamed, an optional becomes required, an enum gains a value. Conformance hits the running server with schema-validating fuzz and asserts response shapes match the published spec.
backwards-compatible" without checking that removing nullability on a response field is a breaking change for consumers. Conformance diffs the new spec against the previously-shipped one and labels every change (additive / behavior / breaking) per the taxonomy in references/versioning-and-deprecation.md.
the spec; that doesn't prove the SDK round-trips successfully against the running server. Conformance runs an end-to-end SDK call for each operation.
/oc-api design)The Designer is a senior API architect who has shipped public APIs to thousands of consumers. Key behaviors:
02-architecture.md(or the ORM schema if it exists) and design resources around the actual entities, not invented ones.
"REST-ish but with one GraphQL endpoint over here." Mixed styles double the surface area.
controls end-to-end. For external consumers, opaque cursors (see references/pagination-and-filtering.md).
status code. Don't ship two error shapes.
every POST/PATCH/DELETE that mutates state. See references/error-and-idempotency.md.
/v1/) or header(API-Version: 2026-04-27) before shipping the first endpoint. Adding versioning retroactively is a migration project.
02-architecture.md API Design and data-model sections,oc-stack-forge's chosen framework + typed-pipeline tooling, oc-reverse-spec inventory (if retrofitting).
api/openapi.yaml (or api/schema.graphql) and present for approval.openapi: 3.1.0
info:
title: [Project] API
version: '1'
description: |
Versioning: URL-based (/v1/, /v2/). Sunset headers on deprecation.
Errors: RFC 9457 problem+json. Pagination: opaque cursor.
servers:
- url: https://oc-api.example.com/v1
security:
- bearerAuth: []
paths:
/widgets:
get:
operationId: listWidgets
parameters:
- { in: query, name: cursor, schema: { type: string } }
- { in: query, name: limit, schema: { type: integer, default: 50, maximum: 200 } }
responses:
'200':
description: Page of widgets
content:
application/json:
schema:
$ref: '#/components/schemas/WidgetPage'
default: { $ref: '#/components/responses/Problem' }
post:
operationId: createWidget
parameters:
- { in: header, name: Idempotency-Key, required: true, schema: { type: string } }
requestBody:
required: true
content:
application/json:
schema: { $ref: '#/components/schemas/WidgetCreate' }
responses:
'201':
description: Created
content:
application/json:
schema: { $ref: '#/components/schemas/Widget' }
default: { $ref: '#/components/responses/Problem' }
components:
securitySchemes:
bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT }
schemas:
Widget:
type: object
required: [id, name, created_at]
properties:
id: { type: string, format: uuid }
name: { type: string }
created_at: { type: string, format: date-time }
WidgetCreate:
type: object
required: [name]
properties:
name: { type: string, minLength: 1, maxLength: 200 }
WidgetPage:
type: object
required: [data]
properties:
data: { type: array, items: { $ref: '#/components/schemas/Widget' } }
next_cursor: { type: [string, 'null'] }
Problem:
type: object
required: [type, title, status]
properties:
type: { type: string, format: uri }
title: { type: string }
status: { type: integer }
detail: { type: string }
instance: { type: string }
responses:
Problem:
description: Error response (RFC 9457)
content:
application/problem+json:
schema: { $ref: '#/components/schemas/Problem' }Present the spec. Confirm resources, auth, error envelope, pagination shape, and versioning strategy with the user. Write checkpoint: phase designed.
/oc-api build)Builder proposes:
## API Build Contract
### Deliverables
- Typed handlers per operationId, generated from the OpenAPI spec
- Request validation middleware (Zod / Pydantic / equivalent for chosen stack)
- RFC 9457 problem+json error formatter applied uniformly
- Idempotency-Key middleware backed by KV / Redis (24h TTL by default)
- Generated SDK (TypeScript via openapi-typescript + openapi-fetch)
- Reference docs (Redoc or Stoplight Elements) at /docs
### Testable Criteria
1. Every operationId has a handler and a request-validation test
2. Every error path returns problem+json with correct `type` URI and `status`
3. Repeated POST with the same Idempotency-Key returns the original response
4. Generated SDK round-trips against the live server for every operation
5. `spectral lint` and `openapi-diff` (vs previous version) report no errorsConformance reviews and pushes back if:
Builder reads the chosen stack from oc-app-architect's 01-tech-stack.md (or, without it, the context_primer.key_decisions of oc-stack-forge's checkpoint — never its private skill_state) and uses the typed-pipeline tooling that oc-stack-forge already recommended:
| Stack (from oc-stack-forge) | Spec authoring | Server validation | SDK generation |
|---|---|---|---|
| Hono + D1 + Workers | @hono/zod-openapi (Zod → OpenAPI) | Hono middleware | openapi-typescript + openapi-fetch |
| FastAPI + Postgres | Pydantic → built-in OpenAPI | FastAPI middleware | openapi-typescript |
| Django + DRF | drf-spectacular | DRF serializers | openapi-typescript |
| Express / Fastify + TS | zod-to-openapi | Zod middleware | openapi-typescript |
| Rails | rswag | Rails strong params | openapi-typescript |
Don't reinvent the toolchain. Read oc-stack-forge/references/typed-pipeline.md (in the installed oc-stack-forge skill) for detailed implementation per stack and pick from that menu; if oc-stack-forge is not installed, the table above is the menu.
Conformance runs in the same session as the Designer and Builder, so its separation is a discipline, not a mechanism: test from the spec and the live server alone — set aside the Builder's implementation choices.
Conformance Persona. A QA engineer who specialises in API contract testing. Key behaviors:
every response against the OpenAPI schema. Mocks are forbidden in this phase.
openapi-diff <prev> <new> — any breaking change must bedeclared (new major version, or explicit Sunset on the old endpoint).
live server and assert the typed response matches.
response must be valid problem+json with the correct type and status.
The second response must be byte-identical to the first.
spectral lint with the project's ruleset must pass clean.Conformance Report saved to api/conformance-round-M.md:
## API Conformance — Round [M]
### Spec → Code Drift
| Operation | Spec status codes | Code status codes | Drift? |
|---|---|---|---|
| listWidgets | 200, 4xx, 5xx | 200, 4xx, 5xx | None |
| createWidget | 201, 4xx, 5xx | 200, 4xx, 5xx | DRIFT — code returns 200 |
### Spec Diff vs Previous Version
- Additive: 2 (new optional fields on Widget)
- Behavior: 0
- Breaking: 1 — `WidgetPage.next_cursor` nullability changed
### SDK Round-Trip
| Operation | SDK call | Response valid | Latency |
|---|---|---|---|
| listWidgets | PASS | PASS | 47ms |
| createWidget | FAIL | — | — |
### Error Envelope
| Status | Triggered? | problem+json valid? |
|---|---|---|
| 400 | Yes | PASS |
| 422 | Yes | FAIL — missing `type` URI |
### Idempotency
| Operation | Repeat returns same body | Status |
|---|---|---|
| createWidget | Yes | PASS |
### Lint
- spectral: 0 errors, 2 warnings
- openapi-diff: 1 breaking change UNDECLARED
### Verdict: PASS / FAIL
[If FAIL: specific failures for Builder to fix]targets declared in the spec to oc-monitoring-ops: invoke the Skill tool with skill "oc-monitoring-ops" and args "/oc-monitor — <API health endpoint + SLO targets from the spec>" — it does not pick them up from this skill on its own.
Max iterations: 3.
/oc-api version — plan a new versionRead references/versioning-and-deprecation.md. Pick URL (/v2/) or header (API-Version: 2026-04-27) — match what's already in production; never mix. Output: a new spec file (api/v2/openapi.yaml) plus a migration guide template under api/migrations/v1-to-v2.md.
/oc-api deprecate — mark endpoints deprecatedFor each deprecated endpoint:
deprecated: true in the spec.Deprecation: <date> (RFC 9745) and Sunset: <date> (RFC 8594) responseheaders.
Link header pointing at the migration guide.api/deprecations.md with the sunset date,the replacement endpoint, and the consumer-notification plan.
/oc-api docs — render human-readable docsDefault: Redoc, served at /docs from the spec file. The Builder must wire the docs route during scaffolding so the rendered docs are always in sync with the shipped spec.
/oc-api sdk — generate SDKTypeScript via openapi-typescript + openapi-fetch is the default; other languages on request. SDK version tracks the API version (v1.x SDK ↔ /v1 API). Publish to a registry only after Conformance round-trip passes.
/oc-api drift — code-vs-spec drift reportRun between commits, in CI, or on demand. Outputs:
Run it in CI (or before /oc-deploy prod) as a recommended check. It is not a deploy gate: oc-deploy-ops's pre-deploy audit gate does not run it, so zero drift is only enforced where you wire it in.
| Concern | Owner | Why |
|---|---|---|
| OAuth flow / API-key handling for consuming a third-party | oc-integrations-engineer | Consumer side |
| Webhook receivers tied to a single integration | oc-integrations-engineer | Lives only because of that third-party |
| Stack/framework recommendation, typed-pipeline tooling | oc-stack-forge | Recommends; oc-api-dev materialises |
Discovery-level "API design" intent in 02-architecture.md | oc-app-architect Phase 2 | Intent; oc-api-dev elaborates |
| Rate-limit infrastructure and capacity math | oc-scale-ops | oc-api-dev declares the policy in the spec; oc-scale-ops sizes / implements |
| Threat model of the API surface | oc-security-auditor | oc-api-dev emits the surface; oc-security-auditor reviews |
| Per-endpoint SLO implementation + alert pipelines | oc-monitoring-ops | oc-api-dev declares SLO targets in the spec; hand them to oc-monitoring-ops, which wires alerts |
| Secret rotation procedures | oc-integrations-engineer /oc-integrate secrets | Already owned |
| PR-facing / product documentation of API changes | oc-docs-forge | oc-api-dev renders reference docs from the spec; oc-docs-forge owns the PR docs packet + product-doc upkeep |
oc-api-dev's outputs (rate-limit policy, CORS policy, SLO targets) are declarations in the spec. Sibling skills implement them when invoked with the spec — none of them reads it unprompted.
oc-stack-forge ships a pack per language under skills/oc-stack-forge/packs/<id>/pack.yml declaring the canonical testRunner, buildCmd, lintCmd, and a langRef. oc-api-dev's Builder phase reads the build-time codegen output src/generated/api-dev-adapters.json to template the right commands into the generated scaffolds.
The codegen runs in prebuild after gen-stack-packs (so the pack contract is already validated) and before gen-flags. Adding a new language pack auto-extends oc-api-dev — no oc-api-dev code changes needed once the pack lands.
That JSON file, the prebuild chain and the test named below exist only in the opchain repo. In any other project, read the same fields straight from the installed oc-stack-forge skill's packs/<id>/pack.yml for the chosen language.
{
"id": "python",
"displayName": "Python",
"status": "stable",
"testRunner": "pytest",
"buildCmd": "python -m build",
"lintCmd": "ruff check .",
"langRef": "language.md"
}status: stable → the adapter is on by default (the coverage flag skills.coverage.<id>.enabled defaults to true). beta / experimental / deprecated packs still appear in the adapter list but are gated by the flag.
oc-api-dev's Builder writes generated source — test stubs, mock servers, CI config fragments. Those need the test/build commands templated in, not looked up at runtime. Codegen produces a stable JSON artifact oc-api-dev can import once and template across many files in one Builder pass. (oc-deploy-ops takes the opposite trade-off — runtime read, because it makes a single dispatch decision per deploy. See oc-deploy-ops/SKILL.md § Pack-aware dispatch.)
api-dev-adapters.json lagsthe packs/ tree. Builder generates scaffolds for the previously-committed baseline. pretest / prebuild regenerate the file, and tests/api-dev-adapters.test.js pins the expected adapter list, so a new pack fails that test until the list is updated.
gen-stack-packs fails first;gen-api-dev-adapters never runs. Builder never sees a partial adapter set.
Frameworks and mobile packs are out of oc-api-dev's surface (frameworks pick up the same language adapter; mobile dispatches through oc-stack-forge's release-checklist path, not oc-api-dev).
The shared checkpoint schema, write rules and resume protocol live in references/checkpoint-protocol.md, bundled with this skill. This section adds only what is specific to oc-api-dev.
{project-dir}/.checkpoints/oc-api-dev.checkpoint.json
| Event | What to Save |
|---|---|
| Contract authored | Style (REST/GraphQL), versioning strategy, auth, operation count |
| Build contract negotiated | Deliverables, criteria, chosen toolchain |
| Builder completes | Files generated, SDK published version, docs URL |
| Conformance runs | Per-operation pass/fail, spec diff classification, lint results |
| Version planned | New version number, breaking changes list, sunset dates |
| Endpoint deprecated | Operation, deprecation date, sunset date, replacement |
{
"style": "rest+openapi3.1",
"versioning": "url",
"current_version": "v1",
"auth": "bearer-jwt",
"operations": 14,
"spec_path": "api/openapi.yaml",
"sdk": { "language": "typescript", "version": "1.3.0" },
"last_conformance": {
"round": 2,
"verdict": "PASS",
"drift_operations": 0,
"spec_diff": { "additive": 1, "behavior": 0, "breaking": 0 }
},
"deprecations": [
{ "operation": "listWidgetsLegacy", "sunset": "2026-10-01" }
]
}| Reads from | Why |
|---|---|
| oc-app-architect | 02-architecture.md API Design + data model → discovery baseline; 01-tech-stack.md → chosen stack; 04-integrations.md carve-outs (inbound webhook receivers stay with oc-integrations-engineer) |
| oc-stack-forge | Chosen framework (context_primer.key_decisions) |
| oc-reverse-spec | Existing-endpoint inventory when retrofitting |
| oc-integrations-engineer | Third-party clients it wired, when this API calls out to them |
| oc-qa-ops | Contract-matrix rows with owner: oc-api-dev → operations the conformance suite must cover (v1.9) |
| Read by | Why |
|---|---|
| oc-integrations-engineer | When a sibling app integrates this API, the published spec is the source of truth |
| oc-docs-forge | API doc/spec drift + generated SDK notes → PR documentation packet |
| oc-qa-ops | API surface → contract-test matrix |
| oc-agent-forge | The published spec as the tool contract for first-party operations in an agent's allowlist |
| oc-signal-forge | Endpoints that expose a metric → the signal's source |
| Hand to (they do not read this checkpoint on their own) | What to pass |
|---|---|
| oc-code-auditor | Scaffolded handlers + api/openapi.yaml, to audit handlers against the spec |
| oc-security-auditor | CORS + rate-limit policy from the spec, as posture inputs |
| oc-monitoring-ops | SLO targets from the spec |
| oc-deploy-ops | A clean /oc-api drift result, as a recommended pre-prod check (not a gate) |
API changes have ripple effects: SDK consumers need lead time on breaking changes; deprecations need calendar visibility; spec drift is a deploy-blocker. v1.2 routes those signals through the PM tool so they're not buried in a checkpoint. See oc-integrations-engineer for the canonical PM-MCP patterns and oc-integrations-engineer/references/pm-mcp-protocol.md for the runtime contract. Record every ticket this section creates or touches in the checkpoint's pm_refs: the breaking-change parent as role: source, per-consumer tickets, the deprecation reminder and api-drift bugs as role: child (this skill authors all of them).
When /oc-api version proposes a major-version bump (or Conformance's openapi-diff — run by /oc-api build and /oc-api test — finds a breaking change in a non-major version), file:
list of breaking endpoints + migration guide.
surface. Consumer registry comes from .opchain/api-consumers.yaml.
Each consumer ticket has the suggested upgrade path + the deadline matching the deprecation policy in .opchain/pm.yaml (deprecation_lead_time: 90d etc.) — an optional key; without it, use the sunset date recorded in api/deprecations.md.
When /oc-api deprecate <endpoint> is invoked:
the PM-MCP) noting the deprecation date.
sunset date with the cleanup checklist.
served on the sunset date, it stays open. No other skill watches the date for you.
/oc-api drift is a recommended pre-deploy check (not an oc-deploy-ops gate). When drift is detected:
implementation diverge in {endpoint}. Reconcile before deploying.`
api-drift-labelled bug-typedchild ticket if it persists across a re-run (one-shot drifts often resolve in the next commit; persistent drift gets a ticket).
When /oc-api sdk produces a new SDK release, post a comment on every linked PM ticket that contributed to the version: SDK {language} v{version} released; includes your change ({endpoint}).
.opchain/api-consumers.yaml → skip the per-consumer fan-out;parent ticket only.
.opchain/pm.yaml, or no deprecation_lead_time in it → takeconsumer deadlines from the sunset dates in api/deprecations.md.
parent ticket only with a query link rather than commenting on each.
fan-out by default; opt-in via /oc-api version --pm-broadcast.
truth. Generate types and SDK from it. Don't write them by hand and hope they agree.
against a live process, not a unit test. Mocks ≠ real.
double the surface area for consumers.
operations." Every POST/PATCH/DELETE.
a new major version with Sunset headers and a migration guide.
SLO targets live in the spec. Sibling skills (oc-scale-ops, oc-monitoring-ops) implement the runtime.
isn't done. Round-trip the SDK against the live server.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.