1. Основа и dependency baseline
- Инициализировать пустой workspace как Git-репозиторий с root package
durable-bun-starter и пятью пакетами: @durable/api, @durable/api-client, @durable/db, @durable/web, @durable/worker.
- Первым artifact создать
.agents/plans/bootstrap-durable-bun-starter.md: дословные требования, файлы, тесты, документацию, риски и порядок TDD. Работа выполняется одним executor без параллельных sibling tasks.
- Перед установкой повторить registry-проверку. Зафиксированный на 2026-07-27 baseline:
| Область | Версии |
|---|
| Runtime | Bun 1.3.14 |
| React | React/DOM 19.2.8, React Compiler 1.0.0 |
| TypeScript/Vite | TypeScript 6.0.3, Vite 8.1.5, React plugin 6.0.4 |
| TanStack | Router 1.170.18, router plugin 1.168.23, Query 5.101.4 |
| API/contracts | Elysia 1.4.29, OpenAPI 1.4.15, Hey API 0.99.0, Zod 4.4.3 |
| Auth/data | Better Auth 1.6.25, Drizzle ORM 0.45.2, Kit 0.31.10, postgres 3.4.9 |
| Temporal | TypeScript SDK 1.21.1, Server 1.31.2, UI 2.52.1 |
| UI | Tailwind 4.3.3, RHF 7.82.0, resolvers 5.4.0, Storybook 10.5.4 |
| Quality | Biome 2.5.5, React Doctor 0.9.1, Playwright 1.61.1, Testcontainers 12.0.4, Turbo 2.10.6 |
| Images | PostgreSQL 18.4-alpine, Caddy 2.11.4, Bun 1.3.14-slim |
- TypeScript 7 не использовать: текущий Hey API 0.99.0 рассчитан на TypeScript 5/6. Temporal 1.21.1 сначала защищается реальным Bun smoke; при воспроизводимой несовместимости единственный fallback — документированный pin на проверенный 1.20.3, без Node runtime.
- Все версии точные;
bunfig.toml содержит minimumReleaseAge = 259200; Docker/GitHub Actions закрепляются digest/SHA. Старые overrides не переносить автоматически: добавлять только после live audit, с upstream issue, записью в docs/security/findings.md и regression check.
- Создать единый
bun.lock, затем доказать воспроизводимость через bun install --frozen-lockfile. Добавить сгруппированный Dependabot для Bun/React/Temporal/testing/Docker/Actions.
2. Публичные интерфейсы и границы
- Dependency graph:
web → api-client; api → db + worker contract subpaths; worker → db; api-client не зависит от backend packages. packages/shared, convenience barrels и циклы запрещены.
createApp(dependencies) в packages/api/src/app.ts остаётся чистым и инфраструктурно независимым; src/index.ts валидирует env, создаёт DB/Auth/Temporal/OTel и слушает порт.
- Использовать same-origin topology: Vite и Caddy проксируют
/api; CORS plugin не устанавливается. Browser client имеет только generated relative URLs и credentials: 'include'.
- HTTP-контракт:
| Endpoint | Контракт |
|---|
POST /api/v1/auth/sign-up | {email,password} → 201 {session} |
POST /api/v1/auth/sign-in | {email,password} → 200 {session} |
POST /api/v1/auth/sign-out | {} → 200 {ok:true} |
GET /api/v1/auth/session | 200 {session: Session | null} |
POST /api/v1/example-operations | {commandId: uuid} → 202 {workflowId,status:'accepted'} |
GET /api/v1/example-operations/{workflowId} | {workflowId,status,result} |
| Health/build | API, worker, web и aggregate aio liveness/readiness; commit/buildTime/release metadata |
- Session содержит только
user.id, нормализованный user.email и expiresAt; API никогда не принимает userId из body. Result операции: {commandId, outcome:'completed'}. Ошибки имеют единый вид {error: {code,message,requestId?,field?}}.
- Каждый endpoint получает Zod request/params/response schemas для всех status codes, стабильный
operationId, tags и явный security guard.
- OpenAPI экспортируется через
app.handle() в .tmp/openapi.json, проходит тестируемый $defs/const/nullable preprocessor и генерирует types, fetch SDK, Zod, query/mutation options и keys. Возможности соответствуют официальным Elysia OpenAPI и Hey API pipeline.
- Package exports только через конкретные subpaths: API app, generated client/query/types/zod, DB client/migrate/schema groups, Worker contracts/workflow. Root
index.ts допускается только как runtime entrypoint или generated artifact.
3. Реализация по подсистемам
- Auth и DB: получить Better Auth schema официальным CLI workflow, добавить
isActive, после чего schema изменяет только Drizzle. Password policy — 12–128 символов; email trim/lowercase. Cookie — HttpOnly, SameSite=Lax, Secure в production. Unsafe commands проверяют Origin по TRUSTED_ORIGINS; production API/AIO падают без BETTER_AUTH_SECRET. Удалённый пользователь теряет session через cascade, неактивный — через facade check. Better Auth handler остаётся внутренней деталью согласно официальной Elysia integration.
- Миграции: auth group,
example_operation и data-task ledger получают явные FK/index/constraint names и timestamptz. Runner держит session advisory lock, выполняет DDL, затем manifest data tasks, закрывает оба соединения в finally и пишет Pino JSON. Tasks имеют monotonic prefix, SHA-256, transactional INSERT … ON CONFLICT, rollback claim и warning при изменённом applied file. db:push:local требует DISPOSABLE_LOCAL_DB=true, development env и отказывает в CI/staging/shared/production.
- Temporal:
workflowId = example-operation:{userId}:{commandId}, reuse policy REJECT_DUPLICATE. Workflow принимает {userId,commandId}, вызывает activity с явными timeout/retry/cancellation и возвращает typed result. Activity идемпотентно сохраняет projection по unique (userId,commandId). Workflow не импортирует DB/runtime и проходит static ban для fetch/filesystem/Math.random/обычного Date.now. Bun worker имеет bounded SIGTERM/SIGINT shutdown и отдельный health server.
- Web: тонкие file routes
/sign-in, /sign-up, /private; loaders используют generated getSessionOptions. Формы используют RHF, generated Zod и локальный confirm-password refinement; server errors связываются с конкретным Field/FormMessage. /private запускает generated mutation, хранит workflowId в URL и polling выполняет generated query options. Logout очищает весь Query cache, поскольку v1 содержит только session-scoped server state.
- UI: использовать актуальный Radix-flavor Frame, FramePanel, FrameHeader и FrameTitle из проверенного ReUI registry; Button/Input/Label/Field брать из shadcn только там, где ReUI не даёт нужного primitive. Зафиксировать принятые auth/private концепты в
docs/architecture/ui-concept; добавить stories для auth, private completed state и operation error. Registry-owned UI исключается из auto-format, но включается в review.
- Observability: Pino JSON с redaction credentials/cookies/tokens; request/user/workflow/run/activity/trace correlation. OTel включается только при
OTEL_EXPORTER_OTLP_ENDPOINT, не передаёт untrusted baggage и завершается с timeout. Локальный collector в v1 не добавляется.
- Runtime: один glibc-based multi-stage image с production dependencies и только runtime artifacts.
tini + entrypoint поддерживают api, web, worker, migrate, aio, healthcheck, shell; Caddy работает non-root на 8080, проксирует API и отдаёт compressed hashed assets с immutable cache. AIO supervisor пересылает сигналы, reaps children, ограничивает shutdown и падает при остановке критического процесса.
- Local development: Compose содержит digest-pinned PostgreSQL, Temporal schema/server/namespace и UI; profile app запускает тот же image во всех ролях. Worktree scripts атомарно выделяют слот через
mkdir, используют отдельные DB/namespace/task queue/app ports, а env merge фиксируется как process env < .env < .env.local < generated isolation values. state.json появляется только после healthchecks; normal stop оставляет stopped tombstone и данные, purge удаляет DB/namespace/slot. Kill разрешён только после PID command ownership check, сначала SIGTERM, затем SIGKILL.
- Governance:
AGENTS.md — канон, CLAUDE.md — короткая ссылка. Создать все требуемые skills: enforce-architecture, test-first-feature, explore-codebase, bug-validation, safe-refactor, openapi-contract-change, drizzle-migration, temporal-workflow, better-auth-change, reui-component, react-doctor, e2e-test, heal-locator, три dev-server-*, review-changes, validate-requirements. Детерминированные skills вызывают scripts, а не пересказывают советы.
- CI/security: отдельные jobs из требования, PR/merge-group triggers, cancellation и timeouts. Biome остаётся единственным formatter/linter; ESLint содержит только React Compiler rule. Добавить Gitleaks с pinned binary/checksum, pinned Semgrep, bun audit, license allowlist, Trivy и dependency review; любое исключение документируется. Threat model покрывает auth/session, generated browser boundary и Temporal command path.
4. Test-first и доказательство готовности
- Каждая подсистема начинается с failing behavioral test: offline OpenAPI; auth cookies/origin/session invalidation; operation ownership/idempotency; workflow/activity; migration empty/upgrade/concurrency; form payload/error mapping; route protection; dev lifecycle; supervisor shutdown.
- Unit suite проверяет schemas, deterministic workflow factory, activity behavior, React state transitions и static architecture guards. Integration suite всегда получает отдельный PostgreSQL/Testcontainers URL и никогда development DB.
- Contract gates повторно генерируют OpenAPI/client и требуют чистый git diff; отдельно запрещают handwritten browser fetch, Better Auth client, Axios/Eden, API literals, custom generated query keys, DB imports в unit tests и forbidden Workflow APIs.
- Playwright выполняет два независимых сценария с уникальными identities: UI registration →
/private → real Temporal completion/result → logout → denial; API-prepared account → UI sign-in → protected page. Используются role/label locators, observable waits, retry trace, failure screenshots, HTML/JUnit. Дополнительно проверить 390×844 без overflow. Resilient locator в v1 не реализовывать.
- Выполнить Storybook build и визуальное сравнение browser screenshots с принятыми концептами через
view_image, включая copy, layout, typography, palette, focus/error states и responsive collapse.
- Финальная последовательность: frozen install → generation/drift → Compose health → migrate →
bun run check → integration/migration/Temporal Bun tests → build/Storybook → Playwright → Docker build → smoke всех пяти ролей → graceful/critical-child tests → Gitleaks/Semgrep/license/audit/Trivy.
- После реализации провести два отдельных read-only прохода:
docs/architecture/code-quality-review.md и requirement matrix с PASS/FAIL и evidence для каждого пункта. Неисправленные FAIL блокируют завершение.
- Оставить PostgreSQL, Temporal и проверенный dev app запущенными; сообщить URLs, slot/state, test counts, image tag/digest и commit. Затем убедиться, что frozen install и повторная генерация не меняют tree, и зафиксировать repository commit без
TODO/FIXME/заглушек.
5. Зафиксированные допущения
- Файлы создаются в текущем каталоге; имя каталога не меняется, но repository/package/image name —
durable-bun-starter.
- UI и тексты английские.
- Frontend/API работают same-origin; permissive или credentialed cross-origin CORS не добавляется.
- Temporal Worker остаётся на Bun и glibc image; Node fallback запрещён.
- GitHub-only
pull_request, merge_group и dependency-review события конфигурируются и инспектируются локально, но не объявляются фактически выполненными без реального GitHub run.