@pikku/skills 0.12.52 → 0.12.54
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.
- package/dist/skills.gen.js +2 -2
- package/package.json +1 -1
- package/skills/pikku-a11y/SKILL.md +22 -15
- package/skills/pikku-addon/SKILL.md +5 -5
- package/skills/pikku-addon/references/addon-package-manifest.md +7 -0
- package/skills/pikku-addon/references/openapi.md +11 -0
- package/skills/pikku-admin-to-fabric/SKILL.md +7 -21
- package/skills/pikku-agent/SKILL.md +6 -6
- package/skills/pikku-agent/references/agents.md +8 -1
- package/skills/pikku-agent/references/runner-vercel.md +2 -2
- package/skills/pikku-agent/references/voice.md +7 -1
- package/skills/pikku-architect/SKILL.md +1 -1
- package/skills/pikku-architect/references/plan-defects.md +2 -0
- package/skills/pikku-auth/SKILL.md +15 -36
- package/skills/pikku-auth/references/better-auth.md +22 -45
- package/skills/pikku-auth/references/jose.md +6 -0
- package/skills/pikku-auth/references/machine-auth.md +6 -0
- package/skills/pikku-auth/references/sessions.md +6 -0
- package/skills/pikku-blueprint-to-fabric/SKILL.md +6 -21
- package/skills/pikku-blueprint-to-fabric/scripts/inventory.mjs +1 -1
- package/skills/pikku-build/SKILL.md +29 -26
- package/skills/pikku-build/references/app.md +60 -41
- package/skills/pikku-build/references/design.md +31 -19
- package/skills/pikku-build/references/feature.md +14 -0
- package/skills/pikku-build/references/mocks.md +23 -0
- package/skills/pikku-build/references/multi-app.md +9 -2
- package/skills/pikku-build/references/native-app.md +9 -0
- package/skills/pikku-build/references/openapi.md +7 -0
- package/skills/pikku-build/references/platform.md +20 -10
- package/skills/pikku-build/references/quick.md +14 -4
- package/skills/pikku-build/references/scenarios.md +12 -1
- package/skills/pikku-build/references/ship.md +6 -1
- package/skills/pikku-build/references/theming.md +74 -125
- package/skills/pikku-changes/SKILL.md +6 -6
- package/skills/pikku-concepts/SKILL.md +8 -17
- package/skills/pikku-concepts/references/concept-mapping.md +18 -0
- package/skills/pikku-convert-screen/SKILL.md +45 -0
- package/skills/pikku-deploy/references/cloudflare.md +8 -0
- package/skills/pikku-deploy/references/lambda.md +8 -0
- package/skills/pikku-deploy/references/uws.md +1 -1
- package/skills/pikku-deploy/references/ws.md +3 -3
- package/skills/pikku-emails/SKILL.md +3 -9
- package/skills/pikku-fabric/SKILL.md +7 -295
- package/skills/pikku-fabric/references/database.md +128 -0
- package/skills/pikku-fabric/references/debugging.md +9 -5
- package/skills/pikku-fabric/references/deploy.md +179 -0
- package/skills/pikku-guide/SKILL.md +10 -10
- package/skills/pikku-i18n/SKILL.md +7 -7
- package/skills/pikku-i18n/references/enum-labels.md +9 -0
- package/skills/pikku-i18n/references/messages.md +16 -3
- package/skills/pikku-i18n/references/rtl.md +18 -38
- package/skills/pikku-knowledge/SKILL.md +9 -10
- package/skills/pikku-kysely/SKILL.md +3 -21
- package/skills/pikku-list-query/SKILL.md +2 -2
- package/skills/pikku-meta/references/audit.md +9 -0
- package/skills/pikku-meta/references/meta.md +6 -0
- package/skills/pikku-meta/references/versioning.md +10 -0
- package/skills/pikku-middleware/SKILL.md +7 -16
- package/skills/pikku-n8n-import/SKILL.md +9 -1
- package/skills/pikku-n8n-import/references/addon-mapping.md +6 -0
- package/skills/pikku-n8n-import/references/code-translation.md +7 -0
- package/skills/pikku-permissions/SKILL.md +41 -10
- package/skills/pikku-permissions/references/scopes.md +59 -0
- package/skills/pikku-react/SKILL.md +2 -2
- package/skills/pikku-react/references/client.md +1 -34
- package/skills/pikku-react/references/react-query.md +11 -0
- package/skills/pikku-react/references/workflows.md +11 -0
- package/skills/pikku-realtime/SKILL.md +9 -3
- package/skills/pikku-report/SKILL.md +10 -9
- package/skills/pikku-scenario/SKILL.md +11 -17
- package/skills/pikku-scenario/references/persona-run.md +11 -1
- package/skills/pikku-scenario/references/personas.md +7 -1
- package/skills/pikku-seo/SKILL.md +12 -16
- package/skills/pikku-service-backends/SKILL.md +0 -10
- package/skills/pikku-service-backends/references/aws.md +6 -0
- package/skills/pikku-service-backends/references/mongodb.md +7 -0
- package/skills/pikku-service-backends/references/redis.md +6 -0
- package/skills/pikku-services/references/audit.md +10 -0
- package/skills/pikku-services/references/config.md +6 -0
- package/skills/pikku-services/references/services.md +8 -1
- package/skills/pikku-software-archaeology/SKILL.md +9 -15
- package/skills/pikku-software-archaeology/references/blueprint.schema.json +7 -7
- package/skills/pikku-software-archaeology/references/pikku-mapping.md +3 -3
- package/skills/pikku-software-archaeology/references/second-opinion.md +13 -1
- package/skills/pikku-tailwind/SKILL.md +111 -0
- package/skills/pikku-theme/SKILL.md +187 -0
- package/skills/pikku-theme/references/from-a-reference.md +44 -0
- package/skills/pikku-theme/references/presets.md +40 -0
- package/skills/pikku-ui/SKILL.md +41 -0
- package/skills/pikku-wiring/SKILL.md +13 -12
- package/skills/pikku-wiring/references/channel.md +7 -1
- package/skills/pikku-wiring/references/cli.md +7 -1
- package/skills/pikku-wiring/references/gateway-slack.md +6 -0
- package/skills/pikku-wiring/references/http.md +10 -3
- package/skills/pikku-wiring/references/mcp.md +8 -0
- package/skills/pikku-wiring/references/queue.md +6 -0
- package/skills/pikku-wiring/references/realtime.md +34 -4
- package/skills/pikku-wiring/references/rpc.md +6 -0
- package/skills/pikku-wiring/references/scheduler.md +6 -0
- package/skills/pikku-wiring/references/trigger.md +8 -0
- package/skills/pikku-workflow/SKILL.md +8 -6
- package/skills/pikku-auth/references/permissions.md +0 -261
- package/skills/pikku-mantine/SKILL.md +0 -80
- package/skills/pikku-wiring/references/realtime-other-routes.md +0 -23
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-a11y
|
|
3
3
|
description: >-
|
|
4
|
-
Accessibility rules (WCAG 2.2) for
|
|
4
|
+
Accessibility rules (WCAG 2.2) for shadcn/Tailwind app UI: labeled inputs, real buttons/links, keyboard and focus, contrast and not-color-alone, modals, reduced motion.
|
|
5
5
|
TRIGGER when: building forms or any interactive UI, icon-only buttons, modals/drawers, tables/lists with actions, keyboard/focus work, or the user mentions accessibility / screen readers / WCAG.
|
|
6
6
|
DO NOT TRIGGER when: working on backend functions, database, or deployment with no UI.
|
|
7
7
|
installGroups: [client]
|
|
@@ -9,24 +9,23 @@ installGroups: [client]
|
|
|
9
9
|
|
|
10
10
|
# Accessibility Rules
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
"properly". They apply to every page
|
|
14
|
-
|
|
12
|
+
shadcn components are accessible ONLY when used properly — the rules below are the
|
|
13
|
+
"properly". They apply to every page, public or logged-in. This skill owns heading hierarchy,
|
|
14
|
+
landmarks and image alt text app-wide (below); `pikku-seo` covers only public-route SEO.
|
|
15
15
|
|
|
16
16
|
## Every input has a label
|
|
17
17
|
|
|
18
|
-
-
|
|
18
|
+
- Give every input a `<Label htmlFor>` — a placeholder is NOT a label (it
|
|
19
19
|
disappears on input and is never announced as one). Placeholder = example value only.
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
- Icon-only controls (`ActionIcon`, icon `Button`) MUST have `aria-label={m.key()}`
|
|
20
|
+
- Wire validation and help text to the input with `aria-describedby` (and `aria-invalid`) — a loose
|
|
21
|
+
red paragraph next to the field is not announced with it.
|
|
22
|
+
- Icon-only controls (icon `Button`) MUST have `aria-label={m.key()}`
|
|
24
23
|
naming the action ("Delete item", not "Trash icon").
|
|
25
24
|
|
|
26
25
|
## Interactive = a real button or link
|
|
27
26
|
|
|
28
|
-
- Never `onClick` on a `div`/`
|
|
29
|
-
readers. Use `Button
|
|
27
|
+
- Never `onClick` on a `div`/`Card` — it is invisible to keyboard and screen
|
|
28
|
+
readers. Use `Button` or `<Link>`; navigation is a
|
|
30
29
|
link (href), actions are buttons.
|
|
31
30
|
- Everything reachable by Tab, activatable by Enter/Space. Never remove focus outlines
|
|
32
31
|
(the theme owns the focus ring), never set `tabIndex` greater than 0, never trap focus
|
|
@@ -38,14 +37,14 @@ covered in the `pikku-seo` skill and apply app-wide, not just on public pages.
|
|
|
38
37
|
|
|
39
38
|
- Status must carry text or an icon, not only a color: a Badge says "Overdue", a form
|
|
40
39
|
error has a message — a red tint by itself is invisible to colorblind users.
|
|
41
|
-
- Contrast comes from the theme; don't undermine it by stacking `
|
|
40
|
+
- Contrast comes from the theme; don't undermine it by stacking `text-muted-foreground` on small
|
|
42
41
|
text over tinted backgrounds. Body copy stays at least AA-readable.
|
|
43
|
-
- Touch targets: WCAG 2.2 minimum 24px — don't shrink
|
|
44
|
-
|
|
42
|
+
- Touch targets: WCAG 2.2 minimum 24px — don't shrink icon buttons or checkboxes below
|
|
43
|
+
24px, and keep adjacent row actions spaced.
|
|
45
44
|
|
|
46
45
|
## Overlays and motion
|
|
47
46
|
|
|
48
|
-
- Modals/drawers: use
|
|
47
|
+
- Modals/drawers: use shadcn `Sheet`/`Dialog` and ALWAYS include a `Title` — that is what
|
|
49
48
|
gets announced; focus trap and Escape come built in. (This project uses drawers, not
|
|
50
49
|
dialogs.)
|
|
51
50
|
- Landing-page animation (the only custom-CSS surface) respects
|
|
@@ -57,3 +56,11 @@ Tab through the page once: every control reachable and visibly focused, every in
|
|
|
57
56
|
labeled, every icon button named, every status readable without color. A browser
|
|
58
57
|
scenario proves the flow works, not that it is reachable without a mouse — this
|
|
59
58
|
manual pass is the only check that does.
|
|
59
|
+
|
|
60
|
+
## Headings, landmarks, alt text (app-wide)
|
|
61
|
+
|
|
62
|
+
- Exactly one h1 per page, naming its topic. Below it: h1 → h2 → h3, no skipped levels.
|
|
63
|
+
Never pick a level for its font size — set the size on the correct level
|
|
64
|
+
(`<h2 className="text-sm">`).
|
|
65
|
+
- Landmarks on every page: `<nav>`, `<main>`, `<footer>` where present (render the element itself, `<nav>`, rather than a `<div>` with a role).
|
|
66
|
+
- Every meaningful `<img>` has alt text describing it; decorative images get `alt=""`.
|
|
@@ -4,11 +4,11 @@ description: >-
|
|
|
4
4
|
Use when creating or consuming reusable function packages (addons) in Pikku. Covers wireAddon,
|
|
5
5
|
ref(), pikkuAddonServices, pikkuAddonWireServices, addon package structure, addons that ship
|
|
6
6
|
database tables (pikku db export), generating an addon from an OpenAPI/Swagger spec, and
|
|
7
|
-
cross-project function sharing. TRIGGER when: code uses wireAddon/ref()/pikkuAddonServices,
|
|
8
|
-
asks about addons, reusable function packages, cross-project sharing
|
|
9
|
-
or
|
|
10
|
-
|
|
11
|
-
definitions (use pikku-concepts).
|
|
7
|
+
cross-project function sharing. TRIGGER when: code uses wireAddon/ref()/pikkuAddonServices, the
|
|
8
|
+
user asks about addons, reusable function packages, cross-project sharing or addon package
|
|
9
|
+
structure, or hands over an OpenAPI/Swagger spec (file or URL) to build on. DO NOT TRIGGER when:
|
|
10
|
+
the user asks about internal function composition (use pikku-wiring), general function
|
|
11
|
+
definitions (use pikku-concepts), or importing an n8n export (use pikku-n8n-import).
|
|
12
12
|
installGroups: [core]
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Addon Package Manifest Reference
|
|
2
2
|
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- Package Structure
|
|
6
|
+
- pikku.config.json
|
|
7
|
+
- package.json (key fields)
|
|
8
|
+
- tsconfig.json (key fields)
|
|
9
|
+
|
|
3
10
|
`npx pikku new addon` scaffolds these files. You rarely hand-edit them — consult this when wiring exports or config by hand.
|
|
4
11
|
|
|
5
12
|
## Package Structure
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# An addon from an OpenAPI spec
|
|
2
2
|
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- Recognising one
|
|
6
|
+
- 1 — Look at the spec first
|
|
7
|
+
- 2 — Generate, from the app's root
|
|
8
|
+
- 3 — Check what was generated
|
|
9
|
+
- 4 — Call it from the app
|
|
10
|
+
- 5 — Verify
|
|
11
|
+
- 6 — Check the spec against the real API
|
|
12
|
+
- Then
|
|
13
|
+
|
|
3
14
|
When you are handed an OpenAPI or Swagger spec — a file, or a URL to one — the
|
|
4
15
|
API it describes becomes an addon: one function per operation, each with its
|
|
5
16
|
input and output schemas, behind one service that makes the HTTP calls. Say so
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-admin-to-fabric
|
|
3
|
-
description: 'Port a legacy back-office admin (ActiveAdmin, Django admin, Rails Admin, Laravel Nova, Filament) to Fabric admin screens, driven by a `.knowledge/` Product Blueprint. Covers the admin-DSL→Fabric mapping (resources→screens, index/column→tables, filter→query params, scope→query variants, member_action/collection_action→pikkuFuncs, permit_params→input schemas), the "the admin is half your app" audit, and admin-specific permissions. TRIGGER when:
|
|
3
|
+
description: 'Port a legacy back-office admin (ActiveAdmin, Django admin, Rails Admin, Laravel Nova, Filament) to Fabric admin screens, driven by a `.knowledge/` Product Blueprint. Covers the admin-DSL→Fabric mapping (resources→screens, index/column→tables, filter→query params, scope→query variants, member_action/collection_action→pikkuFuncs, permit_params→input schemas), the "the admin is half your app" audit, and admin-specific permissions. TRIGGER when: the legacy app being ported has a generated/DSL-driven admin, or the user says "port the admin screens" / "implement the admin"; used per resource alongside pikku-blueprint-to-fabric, which owns the rest of the port. DO NOT TRIGGER when: no legacy admin exists (use pikku-fabric to build screens fresh), no blueprint exists yet (use pikku-software-archaeology), or the app is being extended rather than ported (use pikku-build).'
|
|
4
4
|
installGroups: [fabric]
|
|
5
5
|
argument-hint: '<path to .knowledge/> [resource to port next]'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Legacy admin → Fabric admin screens
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Operating procedure
|
|
11
11
|
|
|
12
12
|
1. **Count first.** How many commands cite the admin? That number decides whether this is a chore or a third of the project.
|
|
13
13
|
2. **The blueprint already has the commands.** Do not re-derive them from the DSL. Map to them.
|
|
@@ -71,10 +71,10 @@ grep -rhoE "(member_action|collection_action) :[a-z_]+" app/admin/*.rb | sort -u
|
|
|
71
71
|
| Legacy | Also called | Becomes in Fabric |
|
|
72
72
|
|---|---|---|
|
|
73
73
|
| `ActiveAdmin.register X` / `class XAdmin` | resource, ModelAdmin, Nova Resource | one TanStack route + one screen |
|
|
74
|
-
| `index do … column :x` | `list_display`, `columns()` | a
|
|
74
|
+
| `index do … column :x` | `list_display`, `columns()` | a shadcn `Table`/data table, columns from the query's return type |
|
|
75
75
|
| `filter :x` | `list_filter`, `searchable` | typed input fields on the list query |
|
|
76
76
|
| `scope :active` | `get_queryset` variants, `Nova::Filters` | a named variant of the list query — NOT a new function per scope |
|
|
77
|
-
| `form do f.input …` | `fields()`, `fieldsets` | a
|
|
77
|
+
| `form do f.input …` | `fields()`, `fieldsets` | a shadcn form; inputs from the command's zod input schema |
|
|
78
78
|
| `permit_params` | `fields`, `$fillable` | you already have this: it is the command's input schema. Cross-check, don't re-derive. |
|
|
79
79
|
| `member_action :foo` | custom action, `Nova::Actions` | **a `pikkuFunc`** — almost always already in `commands.json` |
|
|
80
80
|
| `collection_action :foo` | bulk action | a `pikkuFunc` taking a set |
|
|
@@ -154,7 +154,7 @@ impersonation and editing an FAQ all guarded identically.
|
|
|
154
154
|
- Columns come from the query's return type. If a column exists in the DSL but not
|
|
155
155
|
in the type, the DSL was computing it in Ruby per row — that is an N+1 wearing a
|
|
156
156
|
column, and it belongs in the query.
|
|
157
|
-
- Reuse the app's
|
|
157
|
+
- Reuse the app's theme. An admin styled differently from the product is
|
|
158
158
|
how design systems fork.
|
|
159
159
|
- **Server-computed charts** (chartkick/groupdate and friends) do not port. The
|
|
160
160
|
aggregation becomes a real query; the plot becomes a chart component. This is the
|
|
@@ -190,23 +190,9 @@ Per resource, the parity report records:
|
|
|
190
190
|
| "The admin action isn't in commands.json, I'll add it" | Stop. Either the archaeology missed it (fix the blueprint) or it is dead. Both are findings. |
|
|
191
191
|
| "I'll restyle the admin, it's internal" | An admin off the product's theme is how a design system forks. |
|
|
192
192
|
|
|
193
|
-
## Quick Reference
|
|
194
|
-
|
|
195
|
-
```bash
|
|
196
|
-
# 1. how much of the app is actually the admin?
|
|
197
|
-
node -e "const c=require('./.knowledge/commands.json').commands;console.log(c.filter(x=>(x.evidence||[]).some(e=>(e.file||'').match(/admin/))).length+'/'+c.length)"
|
|
198
|
-
|
|
199
|
-
# 2. inventory the capabilities (not the buttons)
|
|
200
|
-
grep -rhoE "(member_action|collection_action) :[a-z_]+" app/admin/*.rb | sort -u
|
|
201
|
-
|
|
202
|
-
# 3. per resource: map actions -> commands.json, then build the screen
|
|
203
|
-
# 4. verify
|
|
204
|
-
pikku all && pikku fabric validate --json
|
|
205
|
-
```
|
|
206
|
-
|
|
207
193
|
## Related skills
|
|
208
194
|
|
|
209
195
|
- **pikku-software-archaeology** — produces the `.knowledge/` blueprint this needs.
|
|
210
196
|
- **pikku-blueprint-to-fabric** — the parent port; run this per-domain alongside it.
|
|
211
|
-
- **pikku-auth** — roles, ban and impersonation
|
|
212
|
-
- **pikku-fabric** — screens, theme,
|
|
197
|
+
- **pikku-auth** — roles, ban and impersonation; **pikku-permissions** — the scopes that gate them.
|
|
198
|
+
- **pikku-fabric** — screens, theme, shadcn conventions.
|
|
@@ -4,11 +4,11 @@ description: >-
|
|
|
4
4
|
Use when building AI agents, chatbots or LLM-powered assistants with Pikku — pikkuAgent, ref()
|
|
5
5
|
tool registration, memory, streaming, tool approval, thread ownership, invocation via rpc.agent,
|
|
6
6
|
the VercelAgentRunner and its provider map, and the voiceInput/voiceOutput middlewares. TRIGGER
|
|
7
|
-
when: code uses pikkuAgent/rpc.agent/runAgent/streamAgent/VercelAgentRunner/voiceInput,
|
|
8
|
-
about AI agents, chatbots, tool-calling, agent memory or streaming, model providers,
|
|
9
|
-
out, or `pikku enable agent`. DO NOT TRIGGER when: user asks about MCP tool
|
|
10
|
-
pikku-wiring), workflows (use pikku-workflow),
|
|
11
|
-
pikku-concepts).
|
|
7
|
+
when: code uses pikkuAgent/rpc.agent/runAgent/streamAgent/VercelAgentRunner/voiceInput, or the
|
|
8
|
+
user asks about AI agents, chatbots, tool-calling, agent memory or streaming, model providers,
|
|
9
|
+
speech in or out, or `pikku enable agent`. DO NOT TRIGGER when: the user asks about MCP tool
|
|
10
|
+
exposure (use pikku-wiring), workflows (use pikku-workflow), React agent hooks (use pikku-react),
|
|
11
|
+
or general function definitions (use pikku-concepts).
|
|
12
12
|
installGroups: [core]
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -49,7 +49,7 @@ session, the credentials and the RPC depth for you.
|
|
|
49
49
|
`output` schema, and the picture passed as an `attachments` entry.
|
|
50
50
|
- **`auth` defaults to `false`**, because agents are normally invoked from an
|
|
51
51
|
already-authenticated `pikkuFunc`. `scopes` and `permissions` are enforced
|
|
52
|
-
either way — see `pikku-
|
|
52
|
+
either way — see `pikku-permissions`.
|
|
53
53
|
- **`approvalRequired` sits on the tool function, not on the agent.** The run
|
|
54
54
|
then resolves `status: 'suspended'` with `pendingApprovals`; answer with
|
|
55
55
|
`rpc.agent.approve(runId, approvals)`.
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Pikku AI Agent Wiring
|
|
2
2
|
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- Before You Start
|
|
6
|
+
- API Reference
|
|
7
|
+
- Usage Patterns
|
|
8
|
+
- Complete Example
|
|
9
|
+
|
|
3
10
|
|
|
4
11
|
## Before You Start
|
|
5
12
|
|
|
@@ -83,7 +90,7 @@ import cycle.
|
|
|
83
90
|
|
|
84
91
|
`auth` defaults to `false` because agents are usually invoked from an
|
|
85
92
|
already-authenticated `pikkuFunc`. `scopes` and `permissions` are enforced either
|
|
86
|
-
way — see `pikku-
|
|
93
|
+
way — see `pikku-permissions`.
|
|
87
94
|
|
|
88
95
|
### Invoking an agent
|
|
89
96
|
|
|
@@ -25,7 +25,7 @@ const runner = new VercelAgentRunner(
|
|
|
25
25
|
|
|
26
26
|
- `stream(params: AgentRunnerParams, channel: AgentStreamChannel): Promise<AgentStepResult>` — Stream AI responses with tool calls
|
|
27
27
|
- `run(params: AgentRunnerParams): Promise<AgentStepResult>` — Execute a single AI step (non-streaming)
|
|
28
|
-
- `transcribe({ model, audio, … })` / `generateSpeech({ model, text, voice, … })` — what `voiceInput`/`voiceOutput` call; see
|
|
28
|
+
- `transcribe({ model, audio, … })` / `generateSpeech({ model, text, voice, … })` — what `voiceInput`/`voiceOutput` call; see the voice reference
|
|
29
29
|
- `generateImage`, `embed`, `embedMany`, `rerank` — the remaining AI SDK surfaces
|
|
30
30
|
- `withApiKey(apiKey)` — returns a **new** runner built from `providerFactory`; returns `this` unchanged when no factory was supplied or the key is blank. This is the per-user-credential path
|
|
31
31
|
|
|
@@ -85,7 +85,7 @@ export const assistant = pikkuAgent({
|
|
|
85
85
|
```
|
|
86
86
|
|
|
87
87
|
There is no `wireAgent` — agents are declared with `pikkuAgent` from the
|
|
88
|
-
generated agent types.
|
|
88
|
+
generated agent types. The full config is in the agents reference.
|
|
89
89
|
|
|
90
90
|
### Testing without a real provider
|
|
91
91
|
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Pikku AI Voice (Speech I/O)
|
|
2
2
|
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- `@pikku/ai-voice` is deprecated and empty
|
|
6
|
+
- API Reference
|
|
7
|
+
- Usage Pattern
|
|
8
|
+
|
|
3
9
|
|
|
4
10
|
## `@pikku/ai-voice` is deprecated and empty
|
|
5
11
|
|
|
@@ -9,7 +15,7 @@ dependency.
|
|
|
9
15
|
|
|
10
16
|
Voice now lives in **`@pikku/core/agent`** as two AI middlewares, and the
|
|
11
17
|
speech models are reached through the `agentRunner` (`transcribe` /
|
|
12
|
-
`generateSpeech`) rather than through separate services.
|
|
18
|
+
`generateSpeech`) rather than through separate services. The runner reference covers that wiring.
|
|
13
19
|
|
|
14
20
|
## API Reference
|
|
15
21
|
|
|
@@ -3,7 +3,7 @@ name: pikku-architect
|
|
|
3
3
|
description: >-
|
|
4
4
|
Use to turn one claimed changeset into the technical plan its build is measured against —
|
|
5
5
|
the tables, functions, wires, roles, scopes, screens and scenarios it owes, split into passes and
|
|
6
|
-
written through `pikku knowledge plan set
|
|
6
|
+
written through `pikku knowledge plan set`. The plan is the denominator
|
|
7
7
|
`pikku knowledge plan progress` divides by, so it is written BEFORE any of the changeset's code
|
|
8
8
|
exists and never edited afterwards to match what got built. TRIGGER when: `pikku changes
|
|
9
9
|
claim` says a changeset needs a plan, `changes done` or `pikku changes next` refuses one for having no
|
|
@@ -5,6 +5,8 @@ item. These are the ones it cannot, each carried back from a changeset that ship
|
|
|
5
5
|
grouped by the question that finds them, and the fastest way to use this file is to read the six
|
|
6
6
|
questions and only open the group that worries you.
|
|
7
7
|
|
|
8
|
+
## Contents
|
|
9
|
+
|
|
8
10
|
1. [Is this a plan for THIS note?](#is-this-a-plan-for-this-note)
|
|
9
11
|
2. [Does pass 1 slice, and does the model fit inside it?](#does-pass-1-slice-and-does-the-model-fit-inside-it)
|
|
10
12
|
3. [Can each scenario actually be performed?](#can-each-scenario-actually-be-performed)
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-auth
|
|
3
3
|
description: >-
|
|
4
|
-
Use for
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
involved (use pikku-middleware) or
|
|
4
|
+
Use for identity in a Pikku app: authenticating a caller (login, logout, sessions, cookies,
|
|
5
|
+
bearer tokens, API keys, JWT, OAuth/social providers, MFA, Better Auth, machine callers,
|
|
6
|
+
`pikku login`). Covers telling authentication from authorization, the built-in strategies and
|
|
7
|
+
the JWT service. Authorization rules (ownership, roles, scopes, global permissions) live in
|
|
8
|
+
pikku-permissions. TRIGGER when: user asks about login, logout, session, cookie auth, bearer
|
|
9
|
+
tokens, API keys, JWT, Better Auth, social providers, how a CLI/agent/sandbox authenticates,
|
|
10
|
+
or hits InvalidSessionError. DO NOT TRIGGER when: the question is who may call a function,
|
|
11
|
+
such as ownership, roles, per-row checks, scopes or MissingScopeError (use pikku-permissions),
|
|
12
|
+
middleware mechanics with no identity involved (use pikku-middleware), or secrets and env
|
|
13
|
+
vars (use pikku-services).
|
|
13
14
|
installGroups: [core]
|
|
14
15
|
---
|
|
15
16
|
|
|
@@ -28,7 +29,8 @@ Pikku app.
|
|
|
28
29
|
function runs, and ends in a call to `setSession`.
|
|
29
30
|
|
|
30
31
|
**Authorization** answers _may this caller do this_. It is declared on the
|
|
31
|
-
function — `scopes` and `permissions` — never checked inside its body.
|
|
32
|
+
function — `scopes` and `permissions` — never checked inside its body. All of it is
|
|
33
|
+
covered by the pikku-permissions skill.
|
|
32
34
|
|
|
33
35
|
A `permissions` entry that verifies a bearer token and returns `true` is
|
|
34
36
|
authentication wearing an authorization hat: it leaves the function sessionless,
|
|
@@ -39,7 +41,7 @@ middleware instead.
|
|
|
39
41
|
|
|
40
42
|
| You are… | Read |
|
|
41
43
|
| --- | --- |
|
|
42
|
-
| Restricting who may call a function — ownership, roles, scopes |
|
|
44
|
+
| Restricting who may call a function — ownership, roles, scopes | the pikku-permissions skill |
|
|
43
45
|
| Reading or setting the session, or wiring `authBearer`/`authCookie`/`authAPIKey` | `references/sessions.md` |
|
|
44
46
|
| Standing up user sign-in — OAuth, email+password, MFA, organizations | `references/better-auth.md` |
|
|
45
47
|
| Authenticating a CLI, agent, sandbox or worker — API keys, `pikku login` | `references/machine-auth.md` |
|
|
@@ -53,30 +55,8 @@ will not work against them. `references/better-auth.md` has the setup; the
|
|
|
53
55
|
built-in strategies in `references/sessions.md` are how a resolved credential
|
|
54
56
|
becomes a Pikku session, not a replacement for it.
|
|
55
57
|
|
|
56
|
-
## The three gates
|
|
57
|
-
|
|
58
|
-
Authorization is three independent gates, all of which must pass, in this order:
|
|
59
|
-
|
|
60
|
-
1. **Scopes** (`scopes`) — AND'd, checked before input validation, fails closed.
|
|
61
|
-
2. **Global permissions** (`addGlobalPermission`) — AND'd, an app-wide baseline.
|
|
62
|
-
3. **The function's own `permissions`** — OR'd groups of AND'd entries.
|
|
63
|
-
|
|
64
|
-
They are independent: a broad global gate can never satisfy a function's own
|
|
65
|
-
requirement, and a scope can only ever narrow access, never grant it.
|
|
66
|
-
|
|
67
58
|
## What NOT to do
|
|
68
59
|
|
|
69
|
-
- **Do not check authorization inside `func`.** The `permissions` field is
|
|
70
|
-
visible to the inspector; a check in the body is invisible to `pikku info
|
|
71
|
-
permissions` and to an audit. The one sanctioned exception is
|
|
72
|
-
`permissionsInBody`, which is purely declarative — see
|
|
73
|
-
`references/permissions.md`.
|
|
74
|
-
- **Do not write an "is signed in" permission.** `auth: true` (the default on
|
|
75
|
-
`pikkuFunc`) already requires the session. A checker returning `!!session`
|
|
76
|
-
gates nothing.
|
|
77
|
-
- **Do not put `scopes` on a `pikkuSessionlessFunc`.** Scopes fail closed and an
|
|
78
|
-
anonymous caller holds none, so it would reject every caller it exists to
|
|
79
|
-
serve. Gate those with `permissions`, which receive an optional session.
|
|
80
60
|
- **Do not expect the built-in strategies to authenticate a non-HTTP caller.**
|
|
81
61
|
`authBearer`, `authCookie` and `authAPIKey` all step aside when there is no
|
|
82
62
|
HTTP request — a queue job, a scheduled task or a channel message needs its
|
|
@@ -84,6 +64,5 @@ requirement, and a scope can only ever narrow access, never grant it.
|
|
|
84
64
|
- **Do not share one header between the human and machine paths.**
|
|
85
65
|
`Authorization: Bearer` is the human session; `x-api-key` is the machine key.
|
|
86
66
|
Merging them reintroduces the ambiguity the split exists to remove.
|
|
87
|
-
- **Do not
|
|
88
|
-
|
|
89
|
-
are organizational only.
|
|
67
|
+
- **Do not write authorization here.** Ownership, roles, scopes and global
|
|
68
|
+
permissions belong in the `permissions`/`scopes` fields; see pikku-permissions.
|
|
@@ -238,7 +238,7 @@ never needs to know about scopes or roles.
|
|
|
238
238
|
|
|
239
239
|
### The plugins `@pikku/better-auth` ships
|
|
240
240
|
|
|
241
|
-
|
|
241
|
+
Four, all imported from the package root and passed to `betterAuth({ plugins })`
|
|
242
242
|
like any other. None is automatic — an app wires the ones it needs.
|
|
243
243
|
|
|
244
244
|
| Plugin | Plugin `id` | Adds | Use it when |
|
|
@@ -247,12 +247,11 @@ like any other. None is automatic — an app wires the ones it needs.
|
|
|
247
247
|
| `pikkuActor()` | `actor` | `POST /sign-in/actor`, `user.actor` | Scenarios or a dev switcher sign in as a persona |
|
|
248
248
|
| `pikkuCredentialOAuth()` | `credential-oauth` | `POST /credential-oauth/link`, `/credential-oauth/callback/:providerId` | An app links OAuth2 **API credentials** for a user |
|
|
249
249
|
| `pikkuDelegatedAuth()` | `delegated-auth` | `POST /sign-in/delegated` | An imported upstream API is the system of record for identity |
|
|
250
|
-
| `pikkuFabric()` | `fabric` | `POST /sign-in/fabric` | A Fabric-deployed app lets a control-plane operator in |
|
|
251
250
|
|
|
252
251
|
Every one carries a `pikku` prefix, because a `plugins: [...]` array mixes these
|
|
253
252
|
with better-auth's own and a bare `actor()` next to `organization()` says
|
|
254
253
|
nothing about where it came from. The unprefixed names — `ban`, `actor`,
|
|
255
|
-
`credentialOAuth`, `delegatedAuth
|
|
254
|
+
`credentialOAuth`, `delegatedAuth` — are still exported as deprecated
|
|
256
255
|
aliases, so existing apps keep working.
|
|
257
256
|
|
|
258
257
|
The plugin's `id` is what better-auth stores; the **export name** is what the
|
|
@@ -348,21 +347,6 @@ in the `pikku-build` skill's `references/openapi.md`. When the upstream later
|
|
|
348
347
|
refuses the stored token, the addon throws `CredentialRejectedError` (403,
|
|
349
348
|
`reauth: 'sign-in'`): the UI shows the sign-in again.
|
|
350
349
|
|
|
351
|
-
#### `pikkuFabric()` — control-plane operator sign-in
|
|
352
|
-
|
|
353
|
-
```typescript
|
|
354
|
-
pikkuFabric({ publicKey: FABRIC_AUTH_PUBLIC_KEY, scopeService, logger })
|
|
355
|
-
```
|
|
356
|
-
|
|
357
|
-
`POST /sign-in/fabric` verifies a short-lived RS256 token that the Fabric
|
|
358
|
-
control plane signed for an operator session, then signs them into a synthetic
|
|
359
|
-
`fabric-<id>@fabric.internal` row holding the `admin` scope. Asymmetric on
|
|
360
|
-
purpose: the app holds only the public key, so it can never forge an operator
|
|
361
|
-
login, and the same `FABRIC_AUTH_PUBLIC_KEY` is distributed to every stage with
|
|
362
|
-
no per-environment secret. A missing or empty key disables the endpoint, and a
|
|
363
|
-
token whose `purpose` claim is not `fabric-admin` is rejected. Without a
|
|
364
|
-
`ScopeService` the operator signs in holding nothing.
|
|
365
|
-
|
|
366
350
|
### 2. Production database adapter
|
|
367
351
|
|
|
368
352
|
For real deployments swap `memoryAdapter` for the Kysely adapter backed by an injected DB. Better Auth owns its own tables (`user`, `session`, `account`, `verification`, plus plugin tables) — generate its schema with `npx @better-auth/cli generate` and apply it as a migration.
|
|
@@ -534,9 +518,9 @@ an `actor: true` row only under `pikku dev`. With the opt-in set, a stage signs
|
|
|
534
518
|
in as the personas the deployment provisioned when it started and refuses
|
|
535
519
|
everything else (`No actor account exists for that address`), so holding the
|
|
536
520
|
secret on such a stage does not let anyone invent identities. Those rows are
|
|
537
|
-
written by
|
|
538
|
-
stage has no account for, so provisioning needs no actor
|
|
539
|
-
stage whose endpoint is shut.
|
|
521
|
+
written by `provisionPersonas` when an operator sign-in route is asked to act
|
|
522
|
+
as an address the stage has no account for, so provisioning needs no actor
|
|
523
|
+
secret and works on a stage whose endpoint is shut.
|
|
540
524
|
|
|
541
525
|
**`SCENARIO_ACTOR_SECRET` is a credential as powerful as the most privileged
|
|
542
526
|
persona.** Provisioning grants declared roles to actor accounts, so an
|
|
@@ -566,32 +550,27 @@ id to `/sign-in/persona`, both served by
|
|
|
566
550
|
|
|
567
551
|
### Provisioning personas
|
|
568
552
|
|
|
569
|
-
Anywhere but `pikku dev`, the accounts have to exist before anyone signs in.
|
|
570
|
-
|
|
553
|
+
Anywhere but `pikku dev`, the accounts have to exist before anyone signs in.
|
|
554
|
+
`provisionPersonas` creates them from the generated personas:
|
|
571
555
|
|
|
572
556
|
```ts
|
|
573
|
-
import {
|
|
557
|
+
import { provisionPersonas } from '@pikku/better-auth'
|
|
574
558
|
import {
|
|
575
559
|
personaConfigs,
|
|
576
560
|
personaEnvironments,
|
|
577
561
|
} from '#pikku/pikku-personas.gen.js'
|
|
578
562
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
personas: {
|
|
584
|
-
personas: personaConfigs,
|
|
585
|
-
environments: personaEnvironments,
|
|
586
|
-
},
|
|
587
|
-
})
|
|
563
|
+
await provisionPersonas(
|
|
564
|
+
{ auth, scopeService, logger },
|
|
565
|
+
{ personas: personaConfigs, environments: personaEnvironments }
|
|
566
|
+
)
|
|
588
567
|
```
|
|
589
568
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
declaration and looks again. On a stage that
|
|
593
|
-
one query, and the pass only runs when there
|
|
594
|
-
create.
|
|
569
|
+
`auth` only needs to resolve `{ $context }`, so the singleton `services.auth`
|
|
570
|
+
works as is. Call it from whatever route resolves the address a caller wants to
|
|
571
|
+
act as: a miss provisions the declaration and looks again. On a stage that
|
|
572
|
+
already holds the persona that is one query, and the pass only runs when there
|
|
573
|
+
is genuinely something absent to create.
|
|
595
574
|
|
|
596
575
|
**Do not reach for `pikkuServerLifecycle`'s `afterStart` for this.** That hook is
|
|
597
576
|
invoked by `pikku serve` and `pikku dev` and by nothing else — no deploy runtime
|
|
@@ -619,16 +598,14 @@ open. By default provisioning warns about those accounts and changes nothing.
|
|
|
619
598
|
`orphans: 'ban'` shuts them:
|
|
620
599
|
|
|
621
600
|
```ts
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
scopeService,
|
|
626
|
-
personas: {
|
|
601
|
+
await provisionPersonas(
|
|
602
|
+
{ auth, scopeService, logger },
|
|
603
|
+
{
|
|
627
604
|
personas: personaConfigs,
|
|
628
605
|
environments: personaEnvironments,
|
|
629
606
|
orphans: 'ban',
|
|
630
|
-
}
|
|
631
|
-
|
|
607
|
+
}
|
|
608
|
+
)
|
|
632
609
|
```
|
|
633
610
|
|
|
634
611
|
It writes the same `banned` column the console's ban RPC writes (so it needs the
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Pikku Machine Auth
|
|
2
2
|
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- [Human path — `pikku login`](#human-path-pikku-login)
|
|
6
|
+
- [Machine path — API keys](#machine-path-api-keys)
|
|
7
|
+
- [Gotchas](#gotchas)
|
|
8
|
+
|
|
3
9
|
Unified authentication for humans **and** machines against a Pikku + better-auth
|
|
4
10
|
server. Two paths, two headers, one resolver:
|
|
5
11
|
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pikku-blueprint-to-fabric
|
|
3
|
-
description: 'Rebuild a legacy app as a Pikku Fabric app from a `.knowledge/` Product Blueprint (produced by pikku-software-archaeology). Covers the blueprint→Fabric mapping (domains→slices, commands/queries→pikkuFuncs, entities→SQLite migrations, policies→permissions, invariants→DB constraints, workflows→schedulers, frontend-routes→TanStack+
|
|
3
|
+
description: 'Rebuild a legacy app as a Pikku Fabric app from a `.knowledge/` Product Blueprint (produced by pikku-software-archaeology). Covers the blueprint→Fabric mapping (domains→slices, commands/queries→pikkuFuncs, entities→SQLite migrations, policies→permissions, invariants→DB constraints, workflows→schedulers, frontend-routes→TanStack+shadcn), the decisions gate, and the parity report. TRIGGER when: a `.knowledge/` blueprint exists and the user wants to rebuild/port/recreate that app in Pikku or Fabric, or says "rebuild this from the blueprint". Admin screens are ported by pikku-admin-to-fabric alongside it. DO NOT TRIGGER when: no blueprint exists (run pikku-software-archaeology first), the user wants a single new feature in an existing app (use pikku-build), or the task is only the legacy admin screens of an already-started port (use pikku-admin-to-fabric).'
|
|
4
4
|
installGroups: [fabric]
|
|
5
5
|
argument-hint: '<path to .knowledge/> [domain to slice next]'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Blueprint → Fabric
|
|
9
9
|
|
|
10
|
-
##
|
|
11
|
-
|
|
12
|
-
Use this skill as an execution checklist, not reference material.
|
|
10
|
+
## Operating procedure
|
|
13
11
|
|
|
14
12
|
1. **Validate the blueprint before you trust it.** Run the archaeology validator; `0 error(s)` or stop.
|
|
15
13
|
2. **Clear the decisions gate.** Unresolved `decisionsNeeded` block the domains they touch. Ask; do not invent.
|
|
@@ -271,7 +269,7 @@ Two rules:
|
|
|
271
269
|
|
|
272
270
|
## Stage 7 — Frontend
|
|
273
271
|
|
|
274
|
-
Only when `frontend*.json` is present. Target: TanStack Start +
|
|
272
|
+
Only when `frontend*.json` is present. Target: TanStack Start + Tailwind + shadcn.
|
|
275
273
|
|
|
276
274
|
`frontend.json` records the legacy stack as facts. **It is context, not a port target** — a bespoke Sass system, a server-rendered template stack, or a different component library all land on the same target. Read `designSystemConsistency` and `designFindings` to know what _not_ to carry: findings are the drift (hardcoded colors, forked-per-locale pages, duplicated components), and the rebuild is the moment they cost nothing to drop.
|
|
277
275
|
|
|
@@ -287,9 +285,9 @@ Only when `frontend*.json` is present. Target: TanStack Start + Mantine.
|
|
|
287
285
|
|
|
288
286
|
| `rebuild` | What to do |
|
|
289
287
|
| --------------------- | ------------------------------------------------------------------------- |
|
|
290
|
-
| `
|
|
291
|
-
| `
|
|
292
|
-
| `custom-style` | Normalize to
|
|
288
|
+
| `library-standard` | Use the shadcn component. Do not port. |
|
|
289
|
+
| `library-composition` | Compose from shadcn primitives. Do not port. |
|
|
290
|
+
| `custom-style` | Normalize to shadcn + theme tokens. The divergence is the thing to drop. |
|
|
293
291
|
| **`custom-logic`** | **Port the behaviour.** Read `customLogic` and `dependencies`. |
|
|
294
292
|
|
|
295
293
|
The first three are the bulk and they're cheap — they're a re-expression, not a migration. **`custom-logic` is the actual project**: the bespoke chart, the virtualized table, the map surface, the rich editor, the drag interaction. Each has real behaviour that must survive, and `customLogic` says what it is.
|
|
@@ -348,19 +346,6 @@ Per domain:
|
|
|
348
346
|
| "Verify once it's all built" | No bisect point. Verify per slice; that's what slices are for. |
|
|
349
347
|
| "The blueprint has a `low`-confidence entry, I'll build my best guess" | That's inventing product. It's a gate question. |
|
|
350
348
|
|
|
351
|
-
## Quick reference
|
|
352
|
-
|
|
353
|
-
```bash
|
|
354
|
-
node <archaeology-skill>/scripts/validate.mjs <repo>/.knowledge # Stage 0 — must be 0 errors
|
|
355
|
-
# Stage 1 — decisions gate: ask, don't invent
|
|
356
|
-
# Stage 2 — clone starter template, then the post-clone cleanup (pikku-build)
|
|
357
|
-
# Stage 3 — entities.json -> db/sqlite/NNNN-*.sql ; pikku db migrate
|
|
358
|
-
# Stage 4..7 — one domain slice at a time, dependency order
|
|
359
|
-
pikku fabric validate --json
|
|
360
|
-
yarn pikku all && yarn tsc --noEmit
|
|
361
|
-
# Stage 9 — .knowledge/parity-<domain>.md per slice
|
|
362
|
-
```
|
|
363
|
-
|
|
364
349
|
## Relationship to the other skills
|
|
365
350
|
|
|
366
351
|
```
|
|
@@ -334,7 +334,7 @@ p('')
|
|
|
334
334
|
if (feComponents.length) {
|
|
335
335
|
p('## Frontend')
|
|
336
336
|
p('')
|
|
337
|
-
p(`- **${cheapComponents.length}** components are a cheap re-expression in
|
|
337
|
+
p(`- **${cheapComponents.length}** components are a cheap re-expression in the component library (standard / composition / restyle).`)
|
|
338
338
|
p(`- **${customLogic.length}** carry \`custom-logic\` and must be **ported**. This is the real frontend project.`)
|
|
339
339
|
p(`- **${feRoutes.length}** routes → TanStack routes; their \`dataFrom\` names are already the function names above.`)
|
|
340
340
|
p('')
|