@pikku/skills 0.12.52 → 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.
- package/README.md +1 -1
- package/dist/skills.gen.js +2 -2
- package/dist/snippets.js +1 -1
- 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-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 +2 -2
- package/skills/pikku-architect/references/plan-defects.md +9 -7
- package/skills/pikku-auth/SKILL.md +15 -36
- package/skills/pikku-auth/references/better-auth.md +106 -133
- 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-build/SKILL.md +37 -34
- package/skills/pikku-build/references/app.md +113 -99
- package/skills/pikku-build/references/design.md +43 -31
- package/skills/pikku-build/references/feature.md +17 -3
- package/skills/pikku-build/references/mocks.md +29 -0
- package/skills/pikku-build/references/multi-app.md +25 -18
- package/skills/pikku-build/references/native-app.md +9 -0
- package/skills/pikku-build/references/openapi.md +41 -34
- package/skills/pikku-build/references/platform.md +23 -14
- package/skills/pikku-build/references/post-clone.md +1 -1
- package/skills/pikku-build/references/quick.md +76 -39
- package/skills/pikku-build/references/scenarios.md +28 -16
- package/skills/pikku-build/references/ship.md +19 -16
- package/skills/pikku-build/references/theming.md +76 -127
- package/skills/pikku-changes/SKILL.md +7 -10
- package/skills/pikku-concepts/SKILL.md +34 -44
- package/skills/pikku-concepts/references/concept-mapping.md +18 -0
- package/skills/pikku-concepts/references/language.md +6 -6
- 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/nextjs.md +1 -1
- 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-guide/SKILL.md +28 -27
- 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 +21 -9
- package/skills/pikku-i18n/references/rtl.md +18 -38
- package/skills/pikku-knowledge/SKILL.md +12 -13
- package/skills/pikku-kysely/SKILL.md +3 -21
- package/skills/pikku-list-query/SKILL.md +2 -2
- package/skills/pikku-meta/references/audit.md +10 -1
- 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 +20 -22
- package/skills/pikku-react/references/client.md +2 -70
- 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 +17 -16
- package/skills/pikku-scenario/SKILL.md +72 -81
- package/skills/pikku-scenario/references/browser.md +5 -5
- package/skills/pikku-scenario/references/coverage.md +4 -4
- package/skills/pikku-scenario/references/steps.md +31 -30
- package/skills/pikku-scenario/references/{persona-run.md → virtual-user-run.md} +47 -42
- package/skills/pikku-scenario/references/virtual-users.md +114 -0
- 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-wire-service.md +2 -2
- package/skills/pikku-services/references/audit.md +10 -1
- package/skills/pikku-services/references/config.md +6 -0
- package/skills/pikku-services/references/services.md +9 -2
- package/skills/pikku-software-archaeology/SKILL.md +21 -27
- package/skills/pikku-software-archaeology/references/blueprint.schema.json +16 -16
- 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 +9 -7
- package/skills/pikku-admin-to-fabric/SKILL.md +0 -212
- package/skills/pikku-auth/references/permissions.md +0 -261
- package/skills/pikku-blueprint-to-fabric/SKILL.md +0 -377
- package/skills/pikku-blueprint-to-fabric/scripts/inventory.mjs +0 -367
- package/skills/pikku-fabric/SKILL.md +0 -619
- package/skills/pikku-fabric/references/debugging.md +0 -110
- package/skills/pikku-mantine/SKILL.md +0 -80
- package/skills/pikku-scenario/references/personas.md +0 -117
- package/skills/pikku-wiring/references/realtime-other-routes.md +0 -23
package/dist/snippets.js
CHANGED
|
@@ -91,7 +91,7 @@ export const collectSnippets = async (projectDir, into = new Map(), origins = ne
|
|
|
91
91
|
/**
|
|
92
92
|
* A fence that names a region instead of carrying code:
|
|
93
93
|
*
|
|
94
|
-
* ```ts snippet:
|
|
94
|
+
* ```ts snippet:defineVirtualUsers
|
|
95
95
|
* ```
|
|
96
96
|
*
|
|
97
97
|
* The language is optional and kept. Marked fences are replaced whole — both
|
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
|
|
@@ -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
|
|
@@ -285,7 +285,7 @@ one, and is worth opening for any question you cannot answer with a flat yes.
|
|
|
285
285
|
2. **Does pass 1 slice, and does the model fit inside it?** Not "pass 1: the data model, pass 2: the
|
|
286
286
|
API" — and `model` holds only the tables pass 1 or 2 actually migrates, because the model slot has
|
|
287
287
|
no passes and a later table is a PROBLEM from the first day.
|
|
288
|
-
3. **Can each scenario actually be performed?** Name the
|
|
288
|
+
3. **Can each scenario actually be performed?** Name the virtual user; assert what the person got rather
|
|
289
289
|
than that the code ran; write totals as deltas against a database nobody resets; check that every
|
|
290
290
|
input the prose describes is a field somebody planned.
|
|
291
291
|
4. **Does something produce every state and field the plan reads?** For each clause of a description,
|
|
@@ -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)
|
|
@@ -37,8 +39,8 @@ a second changeset — say so in `covers`.
|
|
|
37
39
|
|
|
38
40
|
## Can each scenario actually be performed?
|
|
39
41
|
|
|
40
|
-
**Ask which
|
|
41
|
-
at all.** The runner drives the app as the
|
|
42
|
+
**Ask which virtual user performs it. If the answer is "nobody", it belongs one level up or to no pass
|
|
43
|
+
at all.** The runner drives the app as the virtual users the project declares; there is no anonymous
|
|
42
44
|
RPC caller, so "a caller with no session is refused" is a sentence a backend or permission
|
|
43
45
|
scenario cannot perform. Signed-out is a BROWSER fact.
|
|
44
46
|
|
|
@@ -78,7 +80,7 @@ decision that nothing records.
|
|
|
78
80
|
in this plan, or one already in the meta. Write "when the distributor is removed its companies
|
|
79
81
|
fall back to the direct catalog" with no function that removes a distributor and `plan set`
|
|
80
82
|
accepts it, `plan progress` passes, and the changeset ships a sentence nothing proves. Read each
|
|
81
|
-
description back asking
|
|
83
|
+
description back asking _which function does this_, and cut the half you cannot name.
|
|
82
84
|
|
|
83
85
|
**Where a scenario calls the same function twice, check it for a per-period guard first.** A
|
|
84
86
|
one-per-day, one-per-order or one-per-person rule makes the second call a refusal, so the journey
|
|
@@ -99,14 +101,14 @@ mark a product's countries, cannot be proven without amending the plan mid-build
|
|
|
99
101
|
**Every state a scenario waits in needs the function that leaves the world like that — checked
|
|
100
102
|
against the code ALREADY built.** Three failure shapes, in rising order of cost:
|
|
101
103
|
|
|
102
|
-
-
|
|
104
|
+
- _Stale_: a staff queue of "paid orders with no invoice yet", where an earlier changeset had
|
|
103
105
|
moved invoicing to checkout. No order a customer could place was ever in that state; three
|
|
104
106
|
scenarios passed once against old rows, then failed.
|
|
105
|
-
-
|
|
107
|
+
- _Unreachable_: staff asked to "capture the payment on an authorised order" when no function in
|
|
106
108
|
the app or its addons could put an order in `authorized` — the addon only holds money when
|
|
107
109
|
checkout was started with a flag the plan's own checkout input did not carry.
|
|
108
|
-
-
|
|
109
|
-
distributor and does not show her the product.
|
|
110
|
+
- _Wrong person_: a distributor salon owner planned to buy from a catalogue that is scoped by
|
|
111
|
+
distributor and does not show her the product. Virtual users are not interchangeable.
|
|
110
112
|
|
|
111
113
|
**A `model` slot saying "this changeset adds no table" has to be true of the DATA the scenarios
|
|
112
114
|
read, not only of the entities they name.** One promised a checkout priced by delivery country — a
|
|
@@ -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.
|