@pikku/skills 0.12.54 → 0.12.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +1 -1
  2. package/dist/skills.gen.js +2 -2
  3. package/dist/snippets.js +1 -1
  4. package/package.json +1 -1
  5. package/skills/pikku-architect/SKILL.md +1 -1
  6. package/skills/pikku-architect/references/plan-defects.md +7 -7
  7. package/skills/pikku-auth/references/better-auth.md +92 -96
  8. package/skills/pikku-build/SKILL.md +9 -9
  9. package/skills/pikku-build/references/app.md +56 -61
  10. package/skills/pikku-build/references/design.md +14 -14
  11. package/skills/pikku-build/references/feature.md +3 -3
  12. package/skills/pikku-build/references/mocks.md +6 -0
  13. package/skills/pikku-build/references/multi-app.md +16 -16
  14. package/skills/pikku-build/references/openapi.md +34 -34
  15. package/skills/pikku-build/references/platform.md +4 -5
  16. package/skills/pikku-build/references/post-clone.md +1 -1
  17. package/skills/pikku-build/references/quick.md +63 -36
  18. package/skills/pikku-build/references/scenarios.md +17 -16
  19. package/skills/pikku-build/references/ship.md +14 -16
  20. package/skills/pikku-build/references/theming.md +2 -2
  21. package/skills/pikku-changes/SKILL.md +2 -5
  22. package/skills/pikku-concepts/SKILL.md +26 -27
  23. package/skills/pikku-concepts/references/language.md +6 -6
  24. package/skills/pikku-deploy/references/nextjs.md +1 -1
  25. package/skills/pikku-guide/SKILL.md +18 -17
  26. package/skills/pikku-i18n/references/messages.md +5 -6
  27. package/skills/pikku-knowledge/SKILL.md +3 -3
  28. package/skills/pikku-meta/references/audit.md +1 -1
  29. package/skills/pikku-permissions/SKILL.md +1 -1
  30. package/skills/pikku-react/SKILL.md +18 -20
  31. package/skills/pikku-react/references/client.md +2 -37
  32. package/skills/pikku-report/SKILL.md +10 -10
  33. package/skills/pikku-scenario/SKILL.md +63 -66
  34. package/skills/pikku-scenario/references/browser.md +5 -5
  35. package/skills/pikku-scenario/references/coverage.md +4 -4
  36. package/skills/pikku-scenario/references/steps.md +31 -30
  37. package/skills/pikku-scenario/references/{persona-run.md → virtual-user-run.md} +38 -43
  38. package/skills/pikku-scenario/references/virtual-users.md +114 -0
  39. package/skills/pikku-seo/SKILL.md +1 -1
  40. package/skills/pikku-services/references/audit-wire-service.md +2 -2
  41. package/skills/pikku-services/references/audit.md +1 -2
  42. package/skills/pikku-services/references/services.md +1 -1
  43. package/skills/pikku-software-archaeology/SKILL.md +13 -13
  44. package/skills/pikku-software-archaeology/references/blueprint.schema.json +9 -9
  45. package/skills/pikku-theme/SKILL.md +1 -1
  46. package/skills/pikku-workflow/SKILL.md +1 -1
  47. package/skills/pikku-admin-to-fabric/SKILL.md +0 -198
  48. package/skills/pikku-blueprint-to-fabric/SKILL.md +0 -362
  49. package/skills/pikku-blueprint-to-fabric/scripts/inventory.mjs +0 -367
  50. package/skills/pikku-fabric/SKILL.md +0 -331
  51. package/skills/pikku-fabric/references/database.md +0 -128
  52. package/skills/pikku-fabric/references/debugging.md +0 -114
  53. package/skills/pikku-fabric/references/deploy.md +0 -179
  54. package/skills/pikku-scenario/references/personas.md +0 -123
@@ -1,331 +0,0 @@
1
- ---
2
- name: pikku-fabric
3
- description: 'Build, convert and debug apps on the Pikku Fabric platform. Covers SQLite/libSQL database setup with Kysely, fabric project layout, deploy provider config, the optional `fabric.projectId` in `pikku.config.json`, the `pikku all` + `tsc` verification loop, and reading logs, traces and metrics from a deployed stage. TRIGGER when: user is working on a Fabric-hosted Pikku project, converting an app to Fabric format, asking about Fabric deployment, database or project conventions, asking about a `pikku fabric validate` finding including app-missing-actor-quick-login, or a deployed stage is erroring, timing out or behaving differently than local ("why is prod failing", "check the logs"). DO NOT TRIGGER when: user is working on a generic (non-Fabric) Pikku deployment — use pikku-deploy instead — or the failure reproduces locally, which is where to debug it.'
4
- installGroups: [fabric]
5
- ---
6
-
7
- # Pikku Fabric
8
-
9
- ## Operating procedure
10
-
11
- 1. **Run structural validation first.** Before any edit, run:
12
- ```bash
13
- pikku fabric validate --json
14
- ```
15
- This prints every missing file, misconfigured field, and dependency gap with a `fixHint`. Address all `error` findings before proceeding — they block deploy. Resolve `warn` findings before testing — they cause runtime failures. `info` findings are best-practice gaps that are safe to defer.
16
- 2. Discover before editing. Run the relevant `pikku meta ... --json` command and inspect only the focused output you need.
17
- 3. Identify the source files that own the behavior. Do not start by reading generated output, `.pikku`, `node_modules`, vendored packages, or broad build artifacts.
18
- 4. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
19
- 5. Validate with the narrowest relevant command first, then run `pikku all` when functions, wirings, schemas, or generated clients may have changed.
20
- 6. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
21
-
22
- Fabric is a serverless deployment platform for Pikku apps. Every Fabric app runs on Cloudflare Workers with a SQLite database (via libSQL/Turso). This skill covers what's unique to Fabric. For general Pikku concepts, function authoring, HTTP wiring, and more, see `pikku-concepts`, `pikku-wiring`, `pikku-services`, etc.
23
-
24
- ## Before you start
25
-
26
- ```bash
27
- yarn pikku meta context --json
28
- ```
29
-
30
- Run `pikku meta` before grepping or editing a Fabric app:
31
-
32
- - `pikku meta context --json` for the project map: functions, wires, workflows, capabilities, and source files.
33
- - `pikku meta clients --json` before frontend/RPC work.
34
- - `pikku meta functions --json` to list function ids, then `pikku meta functions get <id> --json` for one function.
35
- - `pikku meta schemas --json` to list schema names. Only request a full schema body with `pikku meta schemas get <name> --json` when you need it.
36
-
37
- Do not load every schema body by default.
38
-
39
- For database work:
40
-
41
- - Use `pikku fabric db schema [--branch <branch>]` for the actual attached Fabric database state: tables and columns.
42
- - Use `pikku meta schemas` for code-level JSON Schema contracts, not database introspection.
43
- - Do not inspect database credentials or connect to the database directly; Fabric already exposes the safe introspection surface.
44
-
45
- ## Database
46
-
47
- Fabric apps use SQLite via Kysely and the libSQL HTTP adapter, not PostgreSQL or D1. `DATABASE_URL` is injected as a variable binding when the stage starts; locally `pikku db migrate` uses a `dev.db` file. Migrations are `.sql` files in `db/sqlite/` at the project root, numbered, gap-free and forward-only; never hand-edit `.pikku/db/schema.gen.ts`. Read `references/database.md` for the `services.ts` setup, the migration guards, dev seed rules and column conventions.
48
-
49
- ## Deploy Provider
50
-
51
- `pikku.config.json` (in the project root, not `packages/functions/`) **must** declare the Fabric deploy provider:
52
-
53
- ```json
54
- {
55
- "deploy": {
56
- "providers": {
57
- "cloudflare": "@pikkufabric/deploy-cloudflare"
58
- }
59
- }
60
- }
61
- ```
62
-
63
- Without this, `pikku deploy plan --provider cloudflare` uses the OSS adapter which lacks Fabric's workflow service wiring.
64
-
65
- The Fabric adapter automatically:
66
-
67
- - Injects `SQLiteKyselyWorkflowService` when `DATABASE_URL` is bound
68
- - Sets up the libSQL workflow queue
69
- - Wires `workflowQueues: true` for the scaffold
70
-
71
- No manual workflow service setup is needed.
72
-
73
- ## Project Layout
74
-
75
- ```
76
- packages/functions/
77
- src/
78
- functions/ # Business logic — one pikkuFunc/workflow per file
79
- wirings/ # Transport bindings
80
- *.http.ts # wireHTTP / defineHTTPRoutes / wireHTTPRoutes
81
- *.channel.ts # wireChannel
82
- *.queue.ts # wireQueueWorker
83
- *.schedule.ts # wireScheduler
84
- *.mcp.ts # wireMCPResource / wireMCPPrompt (an MCP tool is just a function with `mcp: true`)
85
- *.cli.ts # wireCLI
86
- services.ts # pikkuServices factory (singleton)
87
- middleware.ts # Shared middleware
88
- permissions.ts # Shared permissions
89
- .pikku/
90
- db/schema.gen.ts # Kysely types, written by `pikku db migrate` — NEVER hand-edit
91
- apps/app/ # Frontend(s)
92
- db/sqlite/ # Plain .sql migrations, numbered, gap-free (project root)
93
- db/sqlite-dev-seed.sql # Dev-only test data, applied by `pikku db reset`
94
- pikku.config.json # Pikku + deploy config, and the frontends (project root)
95
- ```
96
-
97
- ## How a checkout is linked to its Fabric project
98
-
99
- `fabric.projectId` in `pikku.config.json` names the project. It is optional. Order
100
- tried:
101
-
102
- 1. `FABRIC_PROJECT_ID` env var — CI and scripts.
103
- 2. `fabric.projectId` in `pikku.config.json`.
104
- 3. The git remote, matched against Fabric's projects. The id found is written
105
- into `pikku.config.json` so the lookup happens once. It is never committed
106
- for you; commit it or not. A deploy ignores a `pikku.config.json` whose only
107
- change is `fabric.projectId`. If two projects share one repo the CLI refuses; pick
108
- one with `FABRIC_PROJECT_ID=<projectId>`.
109
-
110
- `pikku fabric config` prints which project, api url and login the current
111
- checkout resolves to, and where each came from, and the project's settings.
112
- The settings Fabric needs that `pikku.config.json` does not describe are stored
113
- on the project, not in a file, and set with `key=value` arguments:
114
-
115
- ```bash
116
- pikku fabric config showcase.name="Watering Log" showcase.tags=voice,realtime
117
- pikku fabric config guide.docs=docs/guide guide.theme.primaryColor=teal
118
- pikku fabric config scenarios.env.STRIPE_MODE=test # the scenario run only
119
- pikku fabric config showcase.tint= # an empty value clears it
120
- ```
121
-
122
- The keys are `showcase.name` (≤60), `showcase.description` (≤160),
123
- `showcase.tags` (comma-separated, ≤6, from Fabric's fixed list),
124
- `showcase.tint` (`#rrggbb`), `guide.docs`, `guide.theme.primaryColor`,
125
- `guide.theme.fontFamily`, `guide.theme.headingFontFamily` and
126
- `scenarios.env.<NAME>`. Every assignment is checked before any is applied, so a
127
- refused one changes nothing. Whether the project appears on the public
128
- showcase is Fabric's decision, not a setting.
129
-
130
- `pikku fabric link` creates
131
- `origin` (with `--gitea`) if there is none, imports the project, writes
132
- `projectId`, and queues the first deploy; it commits and pushes nothing. A
133
- custom production domain is set with `pikku fabric domains add`. Production
134
- always maps to `main`; without a domain it lives on the platform
135
- `*.pikkufabric.app` hostnames.
136
-
137
- The apps are the `frontends` in `pikku.config.json`,
138
- the same list `pikku serve`, `pikku app` and native builds read, and
139
- `pikku fabric validate` and `smoke` read them from there:
140
-
141
- ```json
142
- "frontends": {
143
- "app": {
144
- "cwd": "apps/app",
145
- "primary": true,
146
- "deploy": true,
147
- "kind": "ssr",
148
- "dev": {
149
- "command": ["yarn", "dev"],
150
- "port": 7105,
151
- "healthPath": "/"
152
- }
153
- }
154
- }
155
- ```
156
-
157
- Each `frontends` entry declares a frontend app with its dev command and port.
158
-
159
- ## RPC is the default transport
160
-
161
- In Fabric apps, most features don't need HTTP wirings. Just write the function with `expose: true` — Pikku generates an RPC client and React Query hooks automatically.
162
-
163
- ```typescript
164
- export const listTasks = pikkuSessionlessFunc({
165
- expose: true,
166
- readonly: true,
167
- func: async ({ kysely }, {}) => {
168
- return { tasks: await kysely.selectFrom('tasks').selectAll().execute() }
169
- },
170
- })
171
- ```
172
-
173
- Add `wireHTTP` only when you need a specific REST shape (webhooks, third-party callers).
174
-
175
- ### Transport rule
176
-
177
- - Always use RPC first.
178
- - If the function should be callable from the app or other generated clients, prefer `expose: true`.
179
- - Use `expose: true` for public/generated client access unless the user explicitly wants a private function.
180
- - Do not add HTTP routes unless the user explicitly asks for HTTP/REST, or the project settings explicitly require HTTP transport.
181
- - Every new or changed function must have a real description.
182
- - If function metadata would show `missing description`, the work is not finished yet.
183
-
184
- ## Run it locally
185
-
186
- A Fabric app is two processes: the pikku API server (`:3000`) and the frontend
187
- (vite). The starter template's `bun run dev` starts **both** and takes the whole
188
- session down if either dies — a frontend running against a dead API looks like an
189
- app bug and is the single most common way to waste an hour here.
190
-
191
- ```bash
192
- bun run prebuild # pikku all — codegen must be current before the server boots
193
- bun run dev
194
- ```
195
-
196
- Then open the app, sign up as a real user, and click through what you built.
197
- **HTTP 200 is not evidence.** These are client-rendered pages: the server returns
198
- 200 with an empty shell, so a page whose component throws still looks fine to
199
- curl.
200
-
201
- That pass is a smoke check. Anything you would otherwise verify by hand-driving a
202
- browser tool belongs in a scenario's browser step, run with
203
- `pikku scenario run local --spawn --run browser` — a browser session you steered
204
- yourself proves nothing that re-runs.
205
-
206
- Secrets come from `process.env`, which the CLI populates from a `.env` in the
207
- working directory. `BETTER_AUTH_SECRET` is required — without it the first
208
- sign-up fails with `Requested secret not found`, which names no key and points at
209
- no file. The starter template generates one on first `bun run dev`.
210
-
211
- If you are running the two processes yourself rather than through the template's
212
- script, run `pikku dev` from the **project root** (it resolves `srcDirectories`
213
- relative to the config, so a nested cwd yields a doubled watch path and no hot
214
- reload).
215
-
216
- ## Reaching a model
217
-
218
- An agent needs an `agentRunner` in singleton services, and locally you do not
219
- write one: `pikku dev` builds it from env when it finds a **matching pair** —
220
- `OPENAI_BASE_URL` + `OPENAI_API_KEY`, or `LITELLM_PROXY_URL` + `LITELLM_API_KEY`
221
- — and registers it under `'*'`, so every `provider/model` prefix resolves
222
- through it. With neither pair complete it builds nothing and every agent call
223
- fails with `AIProviderNotConfiguredError` (a 503) — which reads like a broken
224
- agent rather than a missing key, so check `.env` first. Mixing halves is worse
225
- than missing them: a URL from one source with a key from the other 401s on every
226
- call, so the pairs are taken whole, OpenAI first.
227
-
228
- Two ways to fill them in:
229
-
230
- **The Fabric AI gateway.** One key, and every model the gateway fronts —
231
- OpenAI, Anthropic, Google, the OpenRouter catalogue — is reachable by id, billed
232
- through your Fabric account rather than per-vendor:
233
-
234
- ```bash
235
- pikku fabric login
236
- pikku fabric llm key --env >> .env # writes both pairs; --shell and --json also exist
237
- ```
238
-
239
- It mints or reuses a developer-scoped key against your Fabric login. `link` is
240
- not required — the key is yours, not the project's.
241
-
242
- **Your own vendor key.** `OPENAI_BASE_URL=https://api.openai.com/v1` with your
243
- `OPENAI_API_KEY`, and model ids are then only the ones that vendor serves.
244
-
245
- A deployed stage takes the same names through `pikku fabric secrets set` /
246
- `variables set` — the agent units get their runner wired by the bundler, from
247
- those values.
248
-
249
- ## Deploy
250
-
251
- Flow: `pikku fabric login` (needs a human), `pikku fabric init <github url>`, `pikku fabric validate` (must pass clean), then `pikku fabric deploy apply --production -y`. `apply` waits for a terminal state and exits non-zero unless the deployment went live. Read `references/deploy.md` for organization targeting, `--reset`, exit codes, the approval gate (`awaiting_approval`, `needs_config`, `needs_attention`), CI splitting, the upstream guard, the first user and private stage links.
252
-
253
- ## Versioning
254
-
255
- Functions with `expose: true` are versioned via `versions.pikku.json`. When you change a function's input or output schema, you must bump its version number — otherwise `pikku all` will report a breaking change and callers' generated clients become stale.
256
-
257
- `pikku all` catches this automatically.
258
-
259
- ## After every code change
260
-
261
- Run `pikku all` after modifying functions, wirings, or schemas, then `tsc --noEmit`:
262
-
263
- 1. `pikku all` — regenerates all codegen, checks version compliance
264
- 2. `tsc --noEmit` — validates TypeScript types
265
-
266
- Breaking changes are reported by the version check in step 1.
267
-
268
- ### `app-missing-actor-quick-login-<app>`
269
-
270
- The `fabric validate` finding people most often misread. It fires when an app has
271
- a **login screen** but no dev actor switcher, and it is not a style nit: a sandbox
272
- reviewer has no seed password, so without the control they are locked out of the
273
- app they were asked to look at.
274
-
275
- Satisfy it with the starter template's `<DevActorSwitcher />`, or with your
276
- own UI built on `useDevActors()` or `signInAsPersona()` from `@pikku/react` —
277
- validate accepts any of those call sites as evidence, so custom rendering
278
- passes. Either way the server needs `personaSignIn` on `pikkuActor`; see
279
- **pikku-scenario** for it and **pikku-react** for the props.
280
-
281
- The validator also accepts the shapes that predate the package — a hand-rolled
282
- `signInAsActor()` or a literal `POST /auth/sign-in/actor` — so an older app does
283
- not fail the build. **Treat that as a grace period, not the target: migrate those
284
- to `<DevActorSwitcher />`.** They put a per-persona credential in the frontend
285
- bundle, which the persona endpoint exists to avoid.
286
-
287
- Do **not** satisfy it with Better Auth's `/dev/quick-login`. That is a different
288
- endpoint with a different purpose — one fixed admin, not the declared personas —
289
- and it does not clear this rule.
290
-
291
- ## Hard rules
292
-
293
- These apply in every Fabric app:
294
-
295
- - **No `process.env`** — use `variables.get('NAME')` and `secrets.getSecret('NAME')`. Declare with `defineVariable` / `defineSecret`.
296
- - **No `as any`** — fix types properly.
297
- - **No generic `Error`** — throw `NotFoundError`, `ConflictError`, `BadRequestError`, `UnauthorizedError` from `#pikku/error`.
298
- - **No auth checks in function bodies** — use `permissions:` field on the function config with a `pikkuPermission` factory.
299
- - **No hand-editing `.pikku/db/schema.gen.ts`** — write a migration and re-run `pikku db migrate`.
300
- - **One runtime unit per file** — never define multiple functions/workflows in a single source file.
301
- - **Workflow steps don't need manual wiring** — `pikkuSessionlessFunc` step functions in `*.steps.ts` files are auto-discovered by codegen.
302
- - **Identifiers are English** — functions, components, types, files, database tables and columns, in every app whatever market it serves. The team's language is `metaLocale` in `pikku.config.json` and reaches `description`/`title`/`template` only; the app's language is the message catalogue, where `baseLocale` stays `en` and `defaultLocale` decides what a visitor opens in. `pikku fabric validate` warns (`app-base-locale-not-english-<app>`) when an app repoints its base.
303
-
304
- ## Converting an existing app to Fabric format
305
-
306
- Start by running the structural validator — it tells you exactly what is missing:
307
-
308
- ```bash
309
- pikku fabric validate --json
310
- ```
311
-
312
- Fix every `error` and `warn` in the output before continuing. Then:
313
-
314
- 1. **Replace the database layer**: swap PostgreSQL/MySQL queries for Kysely + libSQL. Convert schema to SQLite-compatible SQL migrations in `db/sqlite/`.
315
- 2. **Replace route handlers with pikkuFuncs**: extract business logic into `pikkuFunc`/`pikkuSessionlessFunc`, add `wireHTTP` or `expose: true` for transport.
316
- 3. **Replace DI/IoC with pikkuServices**: move service construction to `createSingletonServices` in `services.ts`.
317
- 4. **Replace `process.env` calls**: plain config becomes `defineVariable` + `variables.get()`, anything sensitive becomes `defineSecret` + `secrets.getSecret()`.
318
- 5. **Add `pikku.config.json`** at project root with `srcDirectories`, `outDir`, and `clientFiles` — plus `metaLocale` if the team does not work in English, which is the language every `description`, `title` and step `template` is then authored in.
319
- 6. **Declare the apps** as `frontends` in `pikku.config.json`. There is no fabric config file; `projectId` is optional; without it the CLI finds the project from the git remote.
320
- 7. **Run `pikku all`** — verify codegen succeeds and there are no type errors.
321
- 8. **Run `pikku fabric validate`** once more to confirm no structural issues remain.
322
-
323
- ## A deployed stage misbehaving
324
-
325
- Reproduce locally first — a deployed stage adds cost and latency to every
326
- iteration, and a failure that reproduces locally is a local debugging problem.
327
- When it only happens deployed, read `references/debugging.md`: start from
328
- `errors` rather than `logs` (they are already filtered and carry the traceId),
329
- follow one trace end to end before forming a theory, and confirm the fix against
330
- the same stage. A deploy that *failed* is a build or config problem and belongs
331
- above, not there.
@@ -1,128 +0,0 @@
1
- # Fabric database: SQLite via libSQL
2
-
3
- ## Contents
4
-
5
- - Setup in `services.ts`
6
- - Migrations
7
- - Dev seed data
8
- - Column conventions
9
-
10
- Fabric apps use SQLite, accessed via Kysely with the libSQL HTTP adapter. NOT PostgreSQL, NOT D1.
11
-
12
- ## Setup in `services.ts`
13
-
14
- ```typescript
15
- import { Kysely, CamelCasePlugin } from 'kysely'
16
- import { LibsqlWebDialect } from '@pikku/kysely-sqlite'
17
- import type { DB } from '#pikku/db/schema.gen.js'
18
-
19
- const databaseUrl = await variables.get('DATABASE_URL')
20
- let kysely: Kysely<DB>
21
- if (databaseUrl) {
22
- kysely = new Kysely<DB>({
23
- dialect: new LibsqlWebDialect({ url: databaseUrl }),
24
- plugins: [new CamelCasePlugin()],
25
- })
26
- } else if (existingServices?.kysely) {
27
- kysely = existingServices.kysely as Kysely<DB>
28
- } else {
29
- throw new Error('kysely not provided and DATABASE_URL is unset')
30
- }
31
- ```
32
-
33
- Fabric injects `DATABASE_URL` as a variable binding when the stage starts. In local dev, `pikku db migrate` uses a local `dev.db` SQLite file.
34
-
35
- ## Migrations
36
-
37
- Migrations are plain `.sql` files at the **project root**, in a directory named
38
- for the engine — `db/sqlite/` for SQLite/libSQL stages, `db/postgres/` for
39
- Postgres ones. Never `db/migrations/`, and never under `packages/functions/`:
40
- the deploy pipeline stages `db/<engine>/*.sql` from the root and applies them
41
- after upload, so a migration anywhere else is silently never run.
42
-
43
- ```
44
- db/sqlite/
45
- 0001-init.sql
46
- 0002-add-users.sql
47
- ```
48
-
49
- Numbers must be consecutive and gap-free, and an applied migration is frozen —
50
- correct a mistake with a new forward migration, never by editing or renaming one
51
- that has already run (the recorded hash will no longer match).
52
-
53
- **Forward-only rule.** Once a migration exists on the base branch (or any stage
54
- has applied it), never edit, rename or delete it — add a NEW numbered migration
55
- that makes the change. A stage records a migration by name and never re-runs it,
56
- so an edit never reaches a database that already applied it. Two guards enforce
57
- this:
58
-
59
- - `pikku fabric validate` reports `migration-modified-after-base-*` (error) for
60
- any `db/<engine>/*.sql` that exists on the base ref (default `origin/main`, else `main`, `origin/master`, `master`,
61
- compared at the branch's merge-base; override with `--migrations-base <ref>`
62
- or `PIKKU_MIGRATIONS_BASE`) but was modified, deleted or renamed in the working
63
- tree. New files are fine. It is skipped outside a git repo or with no base ref.
64
- In CI use a full clone (`fetch-depth: 0`) so the base ref exists.
65
- - `pikku fabric deploy apply` runs the migration-history checks first and
66
- refuses to create a deployment if any fail. It compares against the stage
67
- being deployed and the production (`main`) stage's applied ledger, and against
68
- the base ref — a branch stage can be reset at will, but main's history reaches
69
- production. Findings: `migration-applied-file-missing-*`, `migration-drift-*`,
70
- `migration-gap`, `migration-modified-after-base-*`. Unlike `validate`, a check
71
- that cannot run refuses too: an unreadable ledger (`migration-drift-unchecked`)
72
- or a base ref that does not resolve (`migration-base-unresolved`). There is no
73
- override flag — fix the history.
74
-
75
- Fix a finding by restoring the file (`git checkout origin/main -- db/sqlite/<file>`)
76
- and putting the change in a new migration.
77
-
78
- Run migrations: `pikku db migrate`. It also regenerates `.pikku/db/schema.gen.ts`
79
- (Kysely types) and `.pikku/db/zod.gen.ts` — there is no separate types step.
80
-
81
- **NEVER hand-edit the generated schema** — write a migration and re-run.
82
-
83
- ## Dev seed data
84
-
85
- Alongside the migrations sits `db/<engine>-dev-seed.sql` — `db/sqlite-dev-seed.sql`
86
- or `db/postgres-dev-seed.sql`. There is no seed command. `pikku db reset` is the
87
- only thing that applies it: wipe, migrate, seed. `--no-seed` stops after the
88
- migration, for working on an empty-state or onboarding flow the test data hides.
89
-
90
- Because reset always arrives at a database it has just wiped, **the seed file is
91
- plain `INSERT`s** — no `INSERT OR IGNORE`, no `ON CONFLICT DO NOTHING`, no
92
- `IF NOT EXISTS`. Nothing applies it twice, so it never has to defend itself. If
93
- you find yourself reaching for an idempotent form, that's a sign the data wants
94
- to be a migration instead.
95
-
96
- This is **local dev data only**: enough rows that a fresh dev database isn't an
97
- empty app. Nothing else ever runs it. A deployed stage applies `db/<engine>/*.sql`
98
- and stops there — the one exception is a disposable stage deployed with
99
- `pikku fabric deploy apply <branch> --reset` (see `deploy.md`), which is never
100
- production. Local reset refuses `NODE_ENV=production` and refuses a database
101
- outside the runtime directory.
102
-
103
- So the test is not "is this row realistic?", it is **"would the app be broken
104
- without it in production?"** If yes, it is configuration and belongs in a
105
- migration, however much it looks like sample data. A venue and its rooms, a
106
- product catalogue, a tenant, a country list, the organization the whole
107
- deployment hangs off — all configuration. Accounts and role grants are
108
- provisioning: the fabric plugin's `personas`, or a migration. What is left
109
- over is the seed's job — the bookings, orders and messages a demo needs and a real
110
- environment starts without.
111
-
112
- Get this wrong and it hides: the app is perfect locally, where reset has just
113
- run, and every deployed environment comes up with empty tables. The signature is
114
- a stage whose pages return 200 — the shell renders fine — while its first data
115
- read throws `no result` or a foreign-key violation on a row the seed was
116
- silently supplying.
117
-
118
- A Better Auth app has a second constraint: the plugins you enable (`pikkuBan()`,
119
- `pikkuActor()`, …) each declare columns, and `pikku db migrate` refuses to run while
120
- the applied schema is missing any of them. `pikku db generate` writes the
121
- migration that closes the gap.
122
-
123
- ## Column conventions
124
-
125
- - Use `SERIAL`/`INTEGER PRIMARY KEY AUTOINCREMENT` for IDs
126
- - Use `TEXT` for strings, `INTEGER` for booleans (0/1) and timestamps (Unix ms)
127
- - Use `CHECK` constraints sparingly — prefer app-level validation
128
- - Table and column names: snake_case in SQL, camelCase in TypeScript (via `CamelCasePlugin`)
@@ -1,114 +0,0 @@
1
- # Debugging a deployed Fabric stage
2
-
3
- ## Contents
4
-
5
- - Operating procedure
6
- - The loop (errors, trace, metrics, logs, status)
7
- - Known gaps
8
- - What not to do
9
-
10
- ## Operating procedure
11
-
12
- 1. Reproduce locally first. If it fails locally too, debug it there — the
13
- deployed stage adds cost and latency to every iteration.
14
- 2. Start from `errors`, not `logs`. Errors are already filtered and carry the
15
- traceId that unlocks the rest.
16
- 3. Follow one trace end-to-end before forming a theory. A single failing request
17
- tells you more than a hundred unrelated log lines.
18
- 4. Fix the source cause and redeploy. Never leave the diagnosis at "it is flaky".
19
- 5. Confirm the fix against the same stage — recheck `errors` for the function.
20
-
21
- Every command below requires a logged-in CLI and a linked project. Both fail
22
- with the exact remediation if not:
23
-
24
- ```
25
- Not logged in. Run `pikku fabric login` first.
26
- No fabric project linked. Run `pikku fabric link` first.
27
- ```
28
-
29
- ## The loop
30
-
31
- **1 — What is broken?**
32
-
33
- ```bash
34
- pikku fabric errors -b main # branch defaults to main
35
- pikku fabric errors -b main --function createOrder
36
- ```
37
-
38
- Prints a `WHEN | FUNCTION | TRACE | MESSAGE` table. The message is **truncated
39
- to 100 characters** — treat it as a label, not the full error. The TRACE column
40
- is the input to the next step.
41
-
42
- **2 — What happened in that one request?**
43
-
44
- ```bash
45
- pikku fabric trace <traceId> -b main
46
- pikku fabric trace <traceId> -b main --json
47
- ```
48
-
49
- `--branch` is **required** here (no default). Each event prints as:
50
-
51
- ```
52
- <timestamp> <scriptName> <wireType>:<wireId> <duration>ms — <error|message|outcome>
53
- ```
54
-
55
- This is the whole request across the stage — every unit it touched, in order,
56
- with per-event durations. The last event before the failure is where to look.
57
-
58
- **3 — Is it one request or the whole stage?**
59
-
60
- ```bash
61
- pikku fabric metrics -b main # last 24h
62
- pikku fabric metrics -b main --hours 2 --function createOrder
63
- ```
64
-
65
- `--branch` is **required** here too; `--hours` defaults to 24.
66
-
67
- Rows are `reqs= err= (rate%) avg= min= max=` per bucket. A single bad request
68
- with a healthy error rate is a data problem; a climbing error rate is a
69
- deployment or dependency problem. `--json` additionally returns a `wireTypes`
70
- breakdown (requests per http/queue/scheduler/…) that the table output omits.
71
-
72
- **4 — Wider context around the failure**
73
-
74
- ```bash
75
- pikku fabric logs -b main
76
- pikku fabric logs -b main --level warn
77
- pikku fabric logs -b main -f # follow
78
- ```
79
-
80
- `--branch` is **required** — `logs` throws `Specify --branch <branch-name>.`
81
- without it, even though the flag reads as optional.
82
-
83
- **5 — Is the running code the code you think it is?**
84
-
85
- ```bash
86
- pikku fabric status # active + in-flight deployment, per stage, with gitSha
87
- ```
88
-
89
- Check this _before_ deep-diving. A stage still serving an older `gitSha`, or a
90
- deploy stuck in flight, explains a whole class of "my fix did nothing".
91
-
92
- ## Known gaps — do not misread these as bugs in your app
93
-
94
- - **`pikku fabric logs --since` and `--deployment` are accepted and ignored.**
95
- They are declared as options but the command never reads them, so
96
- `--since 15m` silently returns the same default window as no flag at all. Do
97
- not conclude "nothing happened in the last 15 minutes" from it. Narrow by
98
- `--level`, or by `--function` via `errors`, instead.
99
- - **`--follow` is a 2-second client-side poll, not a server stream** — despite
100
- its own help text reading "Stream new logs (SSE)". The backend does not push
101
- natively. It dedups against what it already printed, so it behaves like `tail -f`, but new
102
- entries can appear up to ~2s late and it holds the process open until killed.
103
-
104
- ## What NOT to do
105
-
106
- - **Do not SSH anywhere or query the telemetry backend directly.** These
107
- commands are the supported surface; anything lower-level is Fabric-internal
108
- and will not exist for your project.
109
- - **Do not debug by redeploying with added `console.log`s.** Get the traceId,
110
- read the trace. A deploy cycle per hypothesis is the slow path.
111
- - **Do not read the truncated `errors` message as the full error.** Always
112
- confirm against `trace` before changing code.
113
- - **Do not treat an empty `errors` table as "the app is fine"** — a request that
114
- returns a wrong 200 logs nothing. Check `metrics` for the outcome mix.