Truestack api design
Honesty-first coding skill set for Claude Code — 21 skills behind an orchestrate router with an enforced governance gate, a code↔memory tally, and auto-research. Built for self-hosted work.
npx -y skills add adtn0810/truestack --skill truestack-api-designAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Design the interface contract for an API before it's implemented — protocol choice, resource and error modeling, versioning, pagination, idempotency, and rate-limit rules. Use whenever the user wants to "design an API", define an "API contract", "contract-first" / "schema-first" work, write or lint an "OpenAPI" / "Swagger" spec, pick "REST vs GraphQL" / "REST vs gRPC" / "which API style", decide "how to version my API" / "deprecate an endpoint" / "sunset header" / a "breaking change" / "backward compatible API", shape an "error response" / "problem+json" / "RFC 9457" / "what status code", add an "idempotency key" / "prevent double charge on retry" / "make POST safe to retry", choose "pagination" / "cursor vs offset" / "next page token", publish "rate limit headers" / design the "429 + quota" policy, do "resource modeling" / "filtering and sorting" query params, "contract testing" / "consumer-driven contracts", or design a "request/response shape" against "mass assignment".
SKILL.md
11.2 KB, as published. Nobody here has run it
truestack-api-design
Own the contract — the promise the API makes to its callers — and get it right before a line of it is implemented. The contract is the artifact; the code conforms to it, not the reverse. Accuracy and stability over cleverness: a boring REST endpoint that every proxy, cache, and client already understands beats a clever one that re-invents what HTTP gave you free.
Read project memory first — CLAUDE.md is auto-loaded (Principles + Boundaries); consult
.ai/memory/ for the stack, existing API conventions, and the reverse proxy in front of the
box. If none exists, run truestack-project-memory. Keep the code↔memory tally balanced: when you
lock a convention (casing, versioning scheme, error type URIs), record it in the same change.
A public-facing or versioned API contract is a high-risk, hard-to-reverse decision — once a
client depends on a shape, you own it. Route the contract through truestack-architecture-planning's
approval gate before it ships, and let truestack-quality-control gate it before "done". Don't guess on a
coin-flip: if more than one reasonable contract fits, clarify with a short, capped round of
questions-with-defaults first.
Auto-research, don't recall: the rules below cite living standards (RFC 9457, RFC 9745/8594, the IETF Idempotency-Key and RateLimit drafts, OWASP API Top 10). Confirm the current status and exact member/header names from the authoritative source before asserting them — drafts advance and status codes have edge cases.
Where this skill sits (seams):
truestack-api-designowns the interface contract;truestack-backend-developmentimplements it (owner-scoped auth, validation, the idempotency table). Define the shape here, build it there.truestack-architecture-planningdoes system design (modules, data flow, services); this skill designs the interface between a service and its callers.- This skill owns the authorization rules in the contract (BOLA/BOPLA below) — the design
discipline.
truestack-quality-controlruns the one-shot SAFETY pass that checks a given change against OWASP; it doesn't author the contract. truestack-application-securityowns the app-wide authz model (RBAC/ABAC, deny-by-default) and the auth flows themselves; this skill specifies object-ownership and field allow-lists inside the contract schema — the interface's slice of that model, not its replacement.truestack-mcp-integrationowns untrusted tool output crossing into the app; this skill owns the request/response schema that validates client input at the edge.truestack-observabilityowns PII redaction in telemetry; keep PII out of URLs/query strings here so it never reaches a log in the first place, but the redaction policy is theirs.truestack-ci-and-deliveryruns the spec lint + backward-compat diff as a CI gate; this skill defines what "breaking" means so that gate has a rule to enforce.
1. Protocol — default REST, justify anything else
REST/JSON over HTTP is the default for a self-hosted single server: debuggable with curl,
CDN/proxy-cacheable, rate-limitable at the edge, no extra infra. Reach past it only for a concrete,
named reason:
- gRPC — internal service-to-service hops where you own both ends and need low latency or streaming. It needs HTTP/2 end-to-end, which many single-box reverse-proxy setups quietly break — verify the path before committing.
- GraphQL — only when many heterogeneous clients cause real over/under-fetching pain. On one server it adds N+1 risk, loses HTTP caching, and hands you a query-cost-limiting burden you now own.
The common mistake: adopting GraphQL/gRPC for resume reasons on a workload REST handles fine, then re-inventing the caching and rate-limiting HTTP gave for free. State the tradeoff; default to REST.
2. Errors are part of the contract — RFC 9457, never 200-with-error
Ship application/problem+json with the standard members — type (a stable, documented URI),
title, status, detail, instance — plus extension members (e.g. errors[] for field-level
validation). The cardinal sin: HTTP 200 with {"error":…}. That lies to every proxy, cache, retry
library, and SLO dashboard — the CDN caches the "error", monitoring shows 100% success while users
fail. Pick the status precisely:
- 400 malformed syntax vs 422 well-formed but semantically invalid.
- 401 "who are you" vs 403 "I know you, denied".
- 409 conflict · 429 throttled.
Clients branch on the stable type URI, not on the human-readable detail string — so type
must never change meaning under a client's feet.
3. Authorization lives in the contract (OWASP API1 BOLA + API3 BOPLA)
The two top API risks are interface-design failures, not code bugs — so they belong here:
- BOLA (object-level): any endpoint taking an object id (
/orders/{id}) must specify owner-scoped authorization in the contract — never trust a guessable id. Prefer non-enumerable ids (UUID/ULID) so the contract doesn't hand attackers a map. - BOPLA / mass-assignment: define explicit request and response schemas — allow-list writable
fields, return-list readable fields. Never bind the request body onto your entity, or a client sets
"role":"admin"(the real GitHub/Twitter breaches). Mark server-controlled fieldsreadOnlyand setadditionalProperties: falseon inputs to reject unknown properties.
truestack-backend-development enforces these at runtime; the contract is where they're specified.
4. Idempotency-Key on every unsafe, retryable write
Any POST/PATCH that creates money or side-effects must accept a client-generated
Idempotency-Key (a UUID) and replay the stored first response on retry — without it, one network
blip double-charges a customer. Full server contract (replay / 409 / 422 semantics, the payload
fingerprint, the one-table implementation) → references/idempotency.md.
5. Pagination — keyset/cursor by default, with a tie-breaker
Use keyset (cursor) pagination over a stable, indexed, unique sort key — OFFSET/LIMIT
degrades and silently skips or duplicates rows when data shifts between page fetches. Cursor
encoding, the non-unique-sort tie-breaker trap, and the narrow offset exception → references/pagination.md.
6. Version in the URI path; deprecate with standard headers
Put the major version in the path (/v1/) — visible in logs, routable by the reverse proxy
without header parsing, trivially CDN-cacheable. Bump the major only for breaking changes; ship
everything backward-compatible without a bump. When retiring a version, every response from it carries
Deprecation (RFC 9745) and Sunset (RFC 8594, an HTTP-date) plus a Link rel="deprecation"
to migration docs. Give a 6–24 month window, then return 410 Gone (not 404/500) after the sunset
date so the deprecation is credible and observable.
7. Define "breaking" precisely — enforce it in CI, not in review
Encode the compatibility rule as a gate; humans miss breakage in PR review.
- Safe (additive, no bump): adding an optional request field, adding a response field, a new endpoint, a new enum value for tolerant readers.
- Breaking (new major): removing/renaming a field, tightening a type or validation, making an
optional input required, removing an enum value, changing a status code or an error
typeURI.
Commit the OpenAPI spec next to the code, lint it on every PR (e.g. Spectral) for
consistency/security rules, and run an automated backward-compat diff to fail the build on any
breaking change. Generate clients/stubs from the spec so it can't drift from the implementation.
truestack-ci-and-delivery wires these as the actual PR checks; this skill supplies the definition they enforce.
8. Rate limit / quota is published, not a surprise 429
Advertise limits with RateLimit (remaining + reset) and RateLimit-Policy (quota + window) headers
so well-behaved clients self-throttle. On a 429 (and a 503) always send Retry-After; when both
are present, prefer Retry-After for the concrete retry delay (RateLimit still advertises the quota/window). Document the limits in the OpenAPI
spec, not just prose. This matters more on a single box: there's no elastic autoscaling, so the rate
limiter is your primary overload-protection and fairness mechanism — size it to what the one box can
actually sustain.
9. Resource & convention discipline — decided once, up front
- Nouns, plural collections (
/orders,/orders/{id}/items); HTTP verbs for actions — no/getOrder,/createOrderin the path. 201 +Locationfor creates, 204 for empty success. - Lock conventions before the first endpoint: one JSON casing (snake_case or camelCase, never both), timestamps as RFC 3339 UTC strings, money as minor-units integers or decimal strings (never floats), explicit nullability.
- Filtering/sorting in query params with a documented allow-list of filterable/sortable fields — an open-ended filter language is an injection and performance footgun on one shared DB.
The hidden cost: inconsistency is itself a breaking-change generator — every later "fix" to a naming or format inconsistency breaks a client. Get it right once.
Honest exit
Claim only what the contract actually specifies and you've verified — a status code, a header name, a standard's current status — against the source, not memory. If a decision turns on a fact you can't ground (a draft's exact member names, whether the proxy passes HTTP/2), say so and abstain rather than assert (honesty contract). When the contract changes a recorded convention or decision, update project memory in the same change; then hand off to truestack-quality-control before "done".
Explain it simply
Say what each choice means in one plain line — "a cursor is a bookmark, not a page number, so it doesn't skip rows when the list shifts under you". Show protocol and versioning tradeoffs as a short list or table, not prose. After designing the contract, state in one line what a client can now rely on that it couldn't before — and hand off to truestack-backend-development to implement it.