@pikku/skills 0.12.34 → 0.12.37

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 (43) hide show
  1. package/README.md +9 -4
  2. package/dist/index.d.ts +7 -4
  3. package/dist/index.js +9 -5
  4. package/dist/skills.gen.d.ts +1 -0
  5. package/dist/skills.gen.js +5 -3
  6. package/dist/snippets.d.ts +26 -0
  7. package/dist/snippets.js +148 -0
  8. package/package.json +2 -2
  9. package/skills/pikku-addon/SKILL.md +41 -30
  10. package/skills/pikku-addon/references/addon-package-manifest.md +9 -4
  11. package/skills/pikku-addon/references/openapi.md +99 -0
  12. package/skills/pikku-agent/references/agents.md +3 -1
  13. package/skills/pikku-architect/SKILL.md +12 -0
  14. package/skills/pikku-auth/references/better-auth.md +16 -0
  15. package/skills/pikku-build/SKILL.md +29 -0
  16. package/skills/pikku-build/references/app.md +52 -4
  17. package/skills/pikku-build/references/feature.md +23 -96
  18. package/skills/pikku-build/references/quick.md +12 -3
  19. package/skills/pikku-changes/SKILL.md +172 -0
  20. package/skills/pikku-concepts/SKILL.md +33 -138
  21. package/skills/pikku-concepts/references/bootstrap.md +58 -0
  22. package/skills/pikku-concepts/references/concept-mapping.md +16 -0
  23. package/skills/pikku-concepts/references/language.md +87 -0
  24. package/skills/pikku-deploy/SKILL.md +1 -1
  25. package/skills/pikku-fabric/SKILL.md +26 -13
  26. package/skills/pikku-guide/SKILL.md +264 -0
  27. package/skills/pikku-knowledge/SKILL.md +10 -0
  28. package/skills/pikku-kysely/SKILL.md +1 -1
  29. package/skills/pikku-mantine/SKILL.md +80 -0
  30. package/skills/pikku-n8n-import/SKILL.md +4 -3
  31. package/skills/pikku-react/references/client.md +12 -0
  32. package/skills/pikku-realtime/SKILL.md +6 -6
  33. package/skills/pikku-report/SKILL.md +143 -0
  34. package/skills/pikku-scenario/SKILL.md +71 -563
  35. package/skills/pikku-scenario/references/browser.md +59 -0
  36. package/skills/pikku-scenario/references/coverage.md +70 -0
  37. package/skills/pikku-scenario/references/personas.md +87 -0
  38. package/skills/pikku-scenario/references/steps.md +366 -0
  39. package/skills/pikku-service-backends/SKILL.md +1 -1
  40. package/skills/pikku-wiring/SKILL.md +1 -1
  41. package/skills/pikku-wiring/references/http.md +8 -0
  42. package/skills/pikku-wiring/references/mcp.md +59 -0
  43. package/skills/pikku-workflow/SKILL.md +7 -8
@@ -186,6 +186,63 @@ When you add a tool, tell whoever asked for it the URL. An assistant that cannot
186
186
  be pointed at an endpoint has not been connected to anything, and `/mcp` is the
187
187
  whole answer.
188
188
 
189
+ ## Authentication
190
+
191
+ An MCP endpoint is not gated as a whole. Pikku already knows, tool by tool, which
192
+ calls need a session, and the endpoint answers accordingly:
193
+
194
+ | Declaration | Anonymous call |
195
+ | ---------------------------------------- | ------------------- |
196
+ | `pikkuSessionlessFunc` with `mcp: true` | runs |
197
+ | the same, plus `auth: true` | `401` + a challenge |
198
+ | `pikkuFunc` with `mcp: true` | `401` + a challenge |
199
+
200
+ ```typescript
201
+ // public: anyone connecting to /mcp can call this
202
+ export const searchCatalog = pikkuSessionlessFunc<Query, Results>({
203
+ mcp: true,
204
+ func: async (services, data) => services.catalog.search(data),
205
+ })
206
+
207
+ // private: an anonymous caller is challenged, never dispatched
208
+ export const myOrders = pikkuFunc<void, Order[]>({
209
+ mcp: true,
210
+ func: async (services, _data, session) =>
211
+ services.orders.forUser(session.userId),
212
+ })
213
+ ```
214
+
215
+ The `401` carries a `WWW-Authenticate` header naming the endpoint's RFC 9728
216
+ Protected Resource Metadata document, which the server also serves — `/mcp` is
217
+ described at `/.well-known/oauth-protected-resource/mcp`. That pair is what an
218
+ MCP client needs to discover an authorization server and start an OAuth flow;
219
+ a refusal delivered as a JSON-RPC result instead reads to a client as a tool that
220
+ failed, and no discovery happens.
221
+
222
+ `tools/list` is never gated, so a client can still see what exists before it has
223
+ a token.
224
+
225
+ Nothing needs configuring: the metadata document defaults to advertising the
226
+ origin the request arrived on, which is right whenever the app is its own
227
+ authorization server. To point elsewhere, pass `mcpAuth` to the runtime:
228
+
229
+ ```typescript
230
+ new PikkuNodeHTTPServer(config, logger, {
231
+ mcpJson,
232
+ mcpAuth: {
233
+ authorizationServers: ['https://auth.example.com'],
234
+ scopesSupported: ['mcp'],
235
+ resourceName: 'Example API',
236
+ },
237
+ })
238
+ ```
239
+
240
+ The transport never verifies a token itself — session resolution stays with the
241
+ app's own middleware, exactly as it works over HTTP. One consequence: only a
242
+ request carrying *no* credentials is challenged. A token that is present but
243
+ expired is dispatched, and the runner's refusal reaches the client as a tool
244
+ error.
245
+
189
246
  ## Red flags
190
247
 
191
248
  | Symptom | Cause |
@@ -195,3 +252,5 @@ whole answer.
195
252
  | Resource returning `{ uri, blob, mimeType }` | Resources are text only: `{ uri, text }` |
196
253
  | Client sees a tool with no description | `mcp: true` without a `description` — check the codegen warning |
197
254
  | `/mcp` 404s | Nothing to serve yet — the mount is skipped until one tool, resource or prompt exists |
255
+ | A tool an assistant should be able to call returns `401` | It is a `pikkuFunc`, or declares `auth: true` — make it a `pikkuSessionlessFunc` if it is genuinely public |
256
+ | A private tool returns a result rather than a challenge | The request carried a credential, so it was dispatched; only a call with none is refused at the door |
@@ -16,12 +16,12 @@ installGroups: [core]
16
16
 
17
17
  Use this skill as an execution checklist, not reference material.
18
18
 
19
- 1. Capture baseline. Run `pikku-verify` (or `pikku all`) BEFORE writing code; note existing errors — only NEW errors are yours to fix.
20
- 2. Discover before editing. Prefer `pikku-meta` / `pikku info functions --verbose` and `pikku info tags --verbose` to see functions usable as steps and project organization; inspect only the focused output you need.
19
+ 1. Capture baseline. Run `pikku all` BEFORE writing code; note existing errors — only NEW errors are yours to fix.
20
+ 2. Discover before editing. Prefer `pikku meta` / `pikku info functions --verbose` and `pikku info tags --verbose` to see functions usable as steps and project organization; inspect only the focused output you need.
21
21
  3. Identify the source files that own the behavior. Do not start from generated output, `.pikku`, `node_modules`, vendored packages, or build artifacts.
22
22
  4. Make the smallest source change. Keep generated files generated — never hand-edit SDKs, schema output, or typegen to paper over errors; fix the source cause.
23
- 5. Validate with the narrowest relevant command, then re-run `pikku-verify`. If only files you did not touch still error, those are pre-existing — leave them unless asked.
24
- 6. Call `pikku-workflow-view` only when `pikku-verify` fully passes (codegen AND type check both green) — never after a partial pass.
23
+ 5. Validate with the narrowest relevant command, then re-run `pikku all`. If only files you did not touch still error, those are pre-existing — leave them unless asked.
24
+ 6. Only claim success when `pikku all` and `tsc` both pass (codegen AND type check green) — never after a partial pass.
25
25
 
26
26
  See `pikku-concepts` for the core mental model.
27
27
 
@@ -33,7 +33,7 @@ The deciding question is: **does any part of this cross an external boundary tha
33
33
 
34
34
  - **Checkout WITH payment → workflow.** Get cart → compute total → **(atomic: create order + order items, deduct stock, clear cart)** → **charge payment through the provider** → send confirmation email. It's a workflow because the payment leg (and the email) are external and must be **retried, not lost, and not charged twice** across a restart — and the user benefits from seeing where the run is.
35
35
  - **Checkout with NO external payment** — e.g. it just records the order and decrements stock in one transaction, nothing leaves the process — is a **single-shot algorithm**: a plain `pikkuFunc` wrapping one `kysely.transaction`. Not a workflow. A workflow here would add durability machinery for a thing that already commits atomically in one shot.
36
- - **One durable step is NOT a workflow — it's a queue worker.** A lone side-effect that must be retried / not lost (send one email, fire one webhook, one external charge) → a **queue worker** (`pikku-queue`), enqueued fire-and-forget. A workflow adds a step graph for a thing that has no steps to orchestrate. (A single non-durable step is just a direct RPC call.)
36
+ - **One durable step is NOT a workflow — it's a queue worker.** A lone side-effect that must be retried / not lost (send one email, fire one webhook, one external charge) → a **queue worker** (see `pikku-wiring`'s queue reference), enqueued fire-and-forget. A workflow adds a step graph for a thing that has no steps to orchestrate. (A single non-durable step is just a direct RPC call.)
37
37
  - Also workflows: onboarding sequences, settlements/payouts, digests and batch sends, anything that waits (`sleep`/`suspend`) or fans out with retries — the common thread is **multiple** steps or a durable wait, never a single step.
38
38
 
39
39
  **HARD RULE — never a single-RPC (one-step) workflow.** A workflow whose body is one `workflow.do('x', 'someRpc', …)` is a mislabeled durable function, not orchestration. Route by durability, NOT into a workflow:
@@ -310,12 +310,11 @@ export const userOnboarding = pikkuWorkflowGraph({
310
310
 
311
311
  ## Step dispatch & HTTP wiring
312
312
 
313
- For per-step inline-vs-queue dispatch (`workflowQueued: true` and the `dispatchStep` rules), the manual `workflowStart`/`workflow`/`workflowStatus` HTTP wirings, and a suspend/resume example, read `references/workflow-reference.md`.
313
+ For per-step inline-vs-queue dispatch (`workflowQueued: true` and the `dispatchStep` rules) and a suspend/resume example, read `references/workflow-reference.md`.
314
314
 
315
315
  ## After writing
316
316
 
317
- 1. `pikku-verify` (codegen + tsc).
317
+ 1. `pikku all`, then `tsc --noEmit` (codegen + type check).
318
318
  2. PKU641 → a `const`/`let` is inside a block; hoist it to the top of the function body.
319
319
  3. Import errors → use `#pikku/workflow/pikku-workflow-types.gen.js`, not `#pikku`.
320
320
  4. Type errors only in files you did not touch → pre-existing template errors; safe to ignore.
321
- 5. Both green → call `pikku-workflow-view` with the workflow name.