KeiSeiKit-1.0/skills/api-design/phase-1-intake.md
Parfii-bot a4e667de10 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

115 lines
4.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 1 — Intake (style, audience, scale, clients)
One free-text paragraph, then three click batches. This is one of only two
phases that accepts typed input (the other is Phase 2's resource list).
## 1a — Ask for the API description
Emit a regular message (NOT AskUserQuestion):
> Describe the API in one paragraph: what problem does it solve, who calls
> it, and any constraint I should know (regulated, existing schema,
> mobile-first, partner network, realtime). Reply in one message.
Store the reply verbatim as `INTAKE`.
## 1b — Style click (AskUserQuestion, single-select)
Reference: `_blocks/api-rest-conventions.md`, `_blocks/api-graphql.md`.
```json
{
"questions": [
{
"question": "Which API style fits the problem?",
"header": "Style",
"multiSelect": false,
"options": [
{"label": "REST + JSON",
"description": "Resource-oriented, HTTP-native, CDN-cacheable. Default for public APIs with heterogeneous clients. See _blocks/api-rest-conventions.md"},
{"label": "GraphQL",
"description": "Client-shaped queries, graph-shaped domain, federation-ready. Apollo / Yoga / async-graphql. See _blocks/api-graphql.md"},
{"label": "tRPC (TypeScript end-to-end)",
"description": "TS-only monorepo; server exports types, client imports. Zero codegen. NOT suitable for multi-language consumers."},
{"label": "gRPC / Protobuf",
"description": "Service-to-service, strong typing, streaming. Over HTTP/2. Browsers need grpc-web. Choose for internal backbones."},
{"label": "Hybrid (REST public + GraphQL internal, or gRPC internal + REST edge)",
"description": "Common at scale — record BOTH surfaces, run this skill twice if needed."}
]
}
]
}
```
Store as `STYLE`. If `Hybrid` → warn user that this skill will design the
PRIMARY surface first; they can re-run for the secondary.
## 1c — Audience + scale click (AskUserQuestion, single-select)
```json
{
"questions": [
{
"question": "Audience + traffic class?",
"header": "Audience+Scale",
"multiSelect": false,
"options": [
{"label": "Public internet, small (<100 rps)",
"description": "Landing-site API, indie SaaS MVP. Rate limit per IP + per key."},
{"label": "Public internet, mid (10010k rps)",
"description": "Growth-stage product. Needs proper quotas, partner tiers, SDK story."},
{"label": "Public internet, large (>10k rps)",
"description": "Stripe / GitHub tier. Date-based versioning, cost-based limits, federation."},
{"label": "Partner / B2B only",
"description": "Known callers, NDA, mTLS or signed requests possible. Simpler abuse surface."},
{"label": "Internal service boundary",
"description": "Inside the VPC / mesh. Skip public rate limits; keep contract tests."}
]
}
]
}
```
Store label components as `AUDIENCE` (public / partner / internal) and
`SCALE` (small / mid / large — internal defaults to `small` unless noted).
## 1d — Clients click (AskUserQuestion, multi-select)
```json
{
"questions": [
{
"question": "Which clients will consume the API?",
"header": "Clients",
"multiSelect": true,
"options": [
{"label": "Web SPA (React / Svelte / Vue)",
"description": "CORS, HttpOnly session cookie or Bearer; SDK in TS"},
{"label": "Mobile native (iOS / Android)",
"description": "Typed SDK (Swift / Kotlin) — favours OpenAPI codegen or GraphQL client"},
{"label": "Server-to-server",
"description": "Partner backends; mTLS, signed requests, long-lived API keys"},
{"label": "CLI / scripts",
"description": "curl-friendly, URL-path versioning preferred, stable query params"},
{"label": "Third-party developers (public docs)",
"description": "Needs Swagger UI / Redoc / Scalar + SDK published to npm / crates.io / PyPI"},
{"label": "Browser form / webhook receiver",
"description": "Content-Type application/x-www-form-urlencoded or webhook body; idempotency-key required"}
]
}
]
}
```
Store as `CLIENTS`. Empty selection → re-ask (an API without a known
client is premature; push back per NO DOWNGRADE with suggested defaults).
## Verify-criterion
- `INTAKE` non-empty (≥40 chars).
- `STYLE` exactly one label.
- `AUDIENCE` and `SCALE` parsed from the Phase 1c label.
- `CLIENTS` has ≥1 entry.
- If `STYLE = tRPC` and `CLIENTS` contains any non-TS client → STOP and
re-ask 1b (tRPC is TS-only; offer REST or GraphQL alternatives per NO
DOWNGRADE).