@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
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# Debugging a deployed Fabric stage
|
|
2
|
-
|
|
3
|
-
## Agent Operating Procedure
|
|
4
|
-
|
|
5
|
-
Use this skill as an execution checklist, not reference material.
|
|
6
|
-
|
|
7
|
-
1. Reproduce locally first. If it fails locally too, debug it there — the
|
|
8
|
-
deployed stage adds cost and latency to every iteration.
|
|
9
|
-
2. Start from `errors`, not `logs`. Errors are already filtered and carry the
|
|
10
|
-
traceId that unlocks the rest.
|
|
11
|
-
3. Follow one trace end-to-end before forming a theory. A single failing request
|
|
12
|
-
tells you more than a hundred unrelated log lines.
|
|
13
|
-
4. Fix the source cause and redeploy. Never leave the diagnosis at "it is flaky".
|
|
14
|
-
5. Confirm the fix against the same stage — recheck `errors` for the function.
|
|
15
|
-
|
|
16
|
-
Every command below requires a logged-in CLI and a linked project. Both fail
|
|
17
|
-
with the exact remediation if not:
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
Not logged in. Run `pikku fabric login` first.
|
|
21
|
-
No fabric project linked. Run `pikku fabric link` first.
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## The loop
|
|
25
|
-
|
|
26
|
-
**1 — What is broken?**
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
pikku fabric errors -b main # branch defaults to main
|
|
30
|
-
pikku fabric errors -b main --function createOrder
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
Prints a `WHEN | FUNCTION | TRACE | MESSAGE` table. The message is **truncated
|
|
34
|
-
to 100 characters** — treat it as a label, not the full error. The TRACE column
|
|
35
|
-
is the input to the next step.
|
|
36
|
-
|
|
37
|
-
**2 — What happened in that one request?**
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
pikku fabric trace <traceId> -b main
|
|
41
|
-
pikku fabric trace <traceId> -b main --json
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
`--branch` is **required** here (no default). Each event prints as:
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
<timestamp> <scriptName> <wireType>:<wireId> <duration>ms — <error|message|outcome>
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
This is the whole request across the stage — every unit it touched, in order,
|
|
51
|
-
with per-event durations. The last event before the failure is where to look.
|
|
52
|
-
|
|
53
|
-
**3 — Is it one request or the whole stage?**
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
pikku fabric metrics -b main # last 24h
|
|
57
|
-
pikku fabric metrics -b main --hours 2 --function createOrder
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
`--branch` is **required** here too; `--hours` defaults to 24.
|
|
61
|
-
|
|
62
|
-
Rows are `reqs= err= (rate%) avg= min= max=` per bucket. A single bad request
|
|
63
|
-
with a healthy error rate is a data problem; a climbing error rate is a
|
|
64
|
-
deployment or dependency problem. `--json` additionally returns a `wireTypes`
|
|
65
|
-
breakdown (requests per http/queue/scheduler/…) that the table output omits.
|
|
66
|
-
|
|
67
|
-
**4 — Wider context around the failure**
|
|
68
|
-
|
|
69
|
-
```bash
|
|
70
|
-
pikku fabric logs -b main
|
|
71
|
-
pikku fabric logs -b main --level warn
|
|
72
|
-
pikku fabric logs -b main -f # follow
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
`--branch` is **required** — `logs` throws `Specify --branch <branch-name>.`
|
|
76
|
-
without it, even though the flag reads as optional.
|
|
77
|
-
|
|
78
|
-
**5 — Is the running code the code you think it is?**
|
|
79
|
-
|
|
80
|
-
```bash
|
|
81
|
-
pikku fabric status # active + in-flight deployment, per stage, with gitSha
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Check this _before_ deep-diving. A stage still serving an older `gitSha`, or a
|
|
85
|
-
deploy stuck in flight, explains a whole class of "my fix did nothing".
|
|
86
|
-
|
|
87
|
-
## Known gaps — do not misread these as bugs in your app
|
|
88
|
-
|
|
89
|
-
- **`pikku fabric logs --since` and `--deployment` are accepted and ignored.**
|
|
90
|
-
They are declared as options but the command never reads them, so
|
|
91
|
-
`--since 15m` silently returns the same default window as no flag at all. Do
|
|
92
|
-
not conclude "nothing happened in the last 15 minutes" from it. Narrow by
|
|
93
|
-
`--level`, or by `--function` via `errors`, instead.
|
|
94
|
-
- **`--follow` is a 2-second client-side poll, not a server stream** — despite
|
|
95
|
-
its own help text reading "Stream new logs (SSE)". Server-side SSE is planned;
|
|
96
|
-
the backend doesn't push natively today. It
|
|
97
|
-
dedups against what it already printed, so it behaves like `tail -f`, but new
|
|
98
|
-
entries can appear up to ~2s late and it holds the process open until killed.
|
|
99
|
-
|
|
100
|
-
## What NOT to do
|
|
101
|
-
|
|
102
|
-
- **Do not SSH anywhere or query the telemetry backend directly.** These
|
|
103
|
-
commands are the supported surface; anything lower-level is Fabric-internal
|
|
104
|
-
and will not exist for your project.
|
|
105
|
-
- **Do not debug by redeploying with added `console.log`s.** Get the traceId,
|
|
106
|
-
read the trace. A deploy cycle per hypothesis is the slow path.
|
|
107
|
-
- **Do not read the truncated `errors` message as the full error.** Always
|
|
108
|
-
confirm against `trace` before changing code.
|
|
109
|
-
- **Do not treat an empty `errors` table as "the app is fine"** — a request that
|
|
110
|
-
returns a wrong 200 logs nothing. Check `metrics` for the outcome mix.
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pikku-mantine
|
|
3
|
-
description: >-
|
|
4
|
-
Use when building a Mantine UI on top of a Pikku backend — rendering dates that came back from a
|
|
5
|
-
generated client, keeping layout flow-relative so the app survives an RTL locale, and branching on
|
|
6
|
-
colour scheme without hardcoding a shade. TRIGGER when: putting a value from usePikkuQuery or an
|
|
7
|
-
RPC response on screen, writing margins/padding/alignment in Mantine props or CSS, choosing a date
|
|
8
|
-
input, or handling light/dark. DO NOT TRIGGER when: the data does not come from a Pikku client
|
|
9
|
-
(this is only about what the generated clients hand you), or for user-facing copy (use pikku-i18n).
|
|
10
|
-
installGroups: [client]
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Mantine on a Pikku client
|
|
14
|
-
|
|
15
|
-
## Dates — always format before rendering
|
|
16
|
-
|
|
17
|
-
The generated clients run `transformDates`, which revives **fully-zoned ISO-8601 instants** —
|
|
18
|
-
`2026-03-14T08:12:00Z`, `2026-03-14T08:12:00.000+01:00` — into `Date` objects and touches nothing
|
|
19
|
-
else. A bare `2026-03-14`, a zoneless `2026-03-14T08:12:00` and an impossible `2026-02-31T00:00:00Z`
|
|
20
|
-
all stay the strings the server sent. So a field's runtime type follows the VALUE, not the schema:
|
|
21
|
-
one column can arrive as a `Date` from one row and a string from the next.
|
|
22
|
-
|
|
23
|
-
Two consequences, and both compile:
|
|
24
|
-
|
|
25
|
-
- **A string method on one white-screens the page.** `row.createdAt.split('T')[0]` type-checks
|
|
26
|
-
against nothing useful and blows up at runtime. There is no string to slice.
|
|
27
|
-
- **A raw `Date` dropped into JSX crashes the route.** `<Text>{row.createdAt}</Text>`, a table cell,
|
|
28
|
-
a `<Badge>` — React throws `Objects are not valid as a React child (found: [object Date])` and the
|
|
29
|
-
page falls into its error boundary. Nothing catches it before the screen is white, which makes it
|
|
30
|
-
the most common broken page in a build.
|
|
31
|
-
|
|
32
|
-
**Format with dayjs.** It is Mantine's own date library, already shipped alongside `@mantine/dates`,
|
|
33
|
-
and it takes either a `Date` or a string. Never `toLocaleDateString`, `date-fns` or `luxon`.
|
|
34
|
-
|
|
35
|
-
```tsx
|
|
36
|
-
import dayjs from 'dayjs'
|
|
37
|
-
|
|
38
|
-
<Text>{dayjs(row.dueOn).format('D MMM YYYY')}</Text> // 15 Jun 2026
|
|
39
|
-
<Text>{dayjs(row.createdAt).format('D MMM YYYY, HH:mm')}</Text>
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
A relative "2 days ago" via dayjs `relativeTime` is fine. Coercing instead of formatting
|
|
43
|
-
(`` `${d}` ``, `String(d)`, `d + ''`) does not crash but prints
|
|
44
|
-
`Mon Jun 15 2026 02:00:00 GMT+0200` — a different bug, equally wrong.
|
|
45
|
-
|
|
46
|
-
Date **inputs** are `@mantine/dates` — `DatePickerInput`, `DatePicker`, `Calendar` — never a raw
|
|
47
|
-
`<TextInput type="date">`. Those are pickers and they are not a schedule: Mantine ships no
|
|
48
|
-
week/time-grid component, so a diary, rota, timetable or booking week is a grid you build, not a
|
|
49
|
-
`Calendar` with the time-of-day left out. `Calendar` with `renderDay` IS right for "a few things on
|
|
50
|
-
each day of a month", like a content calendar or a holiday planner.
|
|
51
|
-
|
|
52
|
-
All of this applies to stub and fixture dates exactly as it does to real data.
|
|
53
|
-
|
|
54
|
-
## RTL-safe styles
|
|
55
|
-
|
|
56
|
-
Write layout styles flow-relative so the UI works in both LTR and RTL languages. Pikku's i18n ships
|
|
57
|
-
Arabic, Hebrew, Farsi and Urdu support, and a physical margin is what breaks under it.
|
|
58
|
-
|
|
59
|
-
| Avoid | Use instead |
|
|
60
|
-
| ----------------------------- | ------------------------------------------ |
|
|
61
|
-
| `ml`, `mr`, `pl`, `pr` | `ms`, `me`, `ps`, `pe` |
|
|
62
|
-
| `text-align: left/right` | `text-align: start/end` |
|
|
63
|
-
| `margin-left`, `margin-right` | `margin-inline-start`, `margin-inline-end` |
|
|
64
|
-
| `flex-direction: row-reverse` | `dir` attribute or logical properties |
|
|
65
|
-
|
|
66
|
-
Mantine shorthand: `ms` = margin-inline-start, `me` = margin-inline-end, `ps` = padding-inline-start,
|
|
67
|
-
`pe` = padding-inline-end.
|
|
68
|
-
|
|
69
|
-
## Dark mode
|
|
70
|
-
|
|
71
|
-
Use Mantine's `light-dark()` utility or `useMantineColorScheme`, and only with colours that already
|
|
72
|
-
come from the theme — never introduce a literal colour or a shade string for one scheme.
|
|
73
|
-
|
|
74
|
-
```tsx
|
|
75
|
-
// Correct
|
|
76
|
-
<Box bg="var(--mantine-color-body)">
|
|
77
|
-
|
|
78
|
-
// Wrong — scheme branch with hardcoded Mantine shades
|
|
79
|
-
<Box bg={theme.colorScheme === 'dark' ? 'dark.6' : 'gray.0'}>
|
|
80
|
-
```
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# Personas and actors
|
|
2
|
-
|
|
3
|
-
A **persona** is a person your product is for; an **actor** is one body that signs in as them. Every entry materialises exactly one actor, so `actors.<id>` exists for each declared persona and there is no second way to declare a login.
|
|
4
|
-
|
|
5
|
-
- Two people of the same kind are two entries, not one persona with two logins — "you see yours, not theirs" is only testable with two customers.
|
|
6
|
-
- Never write an email address: each is derived from the persona id and `scenarios.emailDomain`, and a hand-written one signs in as somebody who was never created.
|
|
7
|
-
- `roles` is typechecked against `defineSystemRole`; an undeclared role is a build error.
|
|
8
|
-
- A person who is only ever acted _upon_ — the account an admin bans — sets `runnable: false`: declared and seeded, never signed in, because a run as them would race the scenario that acts on them.
|
|
9
|
-
- A persona holds only what is true of that kind of person for the app's whole lifetime (`name`, `jobTitle`, `description`, `personality`, `roles`, `goals`, `disposition`). What someone is trying to get done, and the circumstances they are doing it in, belong to the **scenario**, not to them.
|
|
10
|
-
|
|
11
|
-
## Declaring personas in TypeScript
|
|
12
|
-
|
|
13
|
-
There may be **one `definePersonas` call in the whole codebase** — one place to
|
|
14
|
-
read the set from, one place to add to it. A second anywhere, including in the
|
|
15
|
-
same file, is a critical. Generated files are exempt and never claim the slot.
|
|
16
|
-
|
|
17
|
-
> [!WARNING]
|
|
18
|
-
> The declaration is **read from source, never evaluated** — the CLI writes it
|
|
19
|
-
> to JSON that a deployed stage carries without the app. So every value has to
|
|
20
|
-
> be statically knowable, and a value that is not comes out as `undefined`
|
|
21
|
-
> rather than as an error. Only `name` is checked, so a computed `personality`,
|
|
22
|
-
> `jobTitle` or `description` is dropped in silence and the persona runs with a
|
|
23
|
-
> blank temperament.
|
|
24
|
-
|
|
25
|
-
What that admits and what it does not:
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
personality: 'Wound up and short with it.' // read
|
|
29
|
-
personality: `Wound up and short with it.
|
|
30
|
-
Says what she wants in a few blunt words.` // read — no ${} in it
|
|
31
|
-
personality: 'Wound up. ' + 'Short with it.' // dropped, silently
|
|
32
|
-
personality: TEMPERAMENTS.impatient // dropped, silently
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
A no-substitution template literal is a string literal as far as the reader is
|
|
36
|
-
concerned, so it is the way to write a long personality across several lines —
|
|
37
|
-
not a concatenation, and not a `prettier-ignore`d single line. Its newlines and
|
|
38
|
-
leading indentation are kept verbatim and reach the model that way, which is
|
|
39
|
-
harmless but worth knowing before you align it to the surrounding code.
|
|
40
|
-
|
|
41
|
-
One more thing worth knowing before writing a rich persona: **`actor.converse`
|
|
42
|
-
builds its prompt from `name`, `jobTitle`, `personality` and the scenario's
|
|
43
|
-
`task` only.** Fields like `disposition`, `goals` and `roles` are read and
|
|
44
|
-
stored, and the console shows them, but they do not reach the conversing
|
|
45
|
-
persona's instructions. Anything that must shape how someone talks belongs in
|
|
46
|
-
`personality` or in the task.
|
|
47
|
-
|
|
48
|
-
A project that never declares a persona keeps working: a scenario that names no actor needs none.
|
|
49
|
-
|
|
50
|
-
- `environments.<name>.apiUrl` is required. `signInPath` defaults to `/auth/sign-in/actor`, `rpcPath` to `/rpc`.
|
|
51
|
-
- **`SCENARIO_ACTOR_SECRET` is an environment variable and never goes in `pikku.config.json`.** It signs actors in. `pikku scenario run` throws without it; a server auto-building actors warns and runs without them.
|
|
52
|
-
|
|
53
|
-
## Actors that call a third-party API
|
|
54
|
-
|
|
55
|
-
An addon generated from an upstream API (Dolibarr, a CRM, a calendar) calls it
|
|
56
|
-
with the signed-in user's own credential. An actor has none until one is stored
|
|
57
|
-
for it, so every step that reaches the addon fails with `No <X> session`. Give
|
|
58
|
-
the `actor` plugin a `credentials` option, and each actor carries its upstream
|
|
59
|
-
credential into every session:
|
|
60
|
-
|
|
61
|
-
- `names: ['dolibarr']` — the credentials to carry
|
|
62
|
-
- `store: (name, value, userId) => credentialService.set(name, value, userId)`
|
|
63
|
-
- `remove: (name, userId) => credentialService.delete(name, userId)`
|
|
64
|
-
|
|
65
|
-
At each actor sign-in the plugin reads `ACTOR_CREDENTIAL_<PERSONA>_<NAME>` —
|
|
66
|
-
`dan` + `dolibarr` is `ACTOR_CREDENTIAL_DAN_DOLIBARR` — and stores it with
|
|
67
|
-
`credentialService.set` for that actor. A bare value is stored as `{ token }`
|
|
68
|
-
(what a delegated or bearer credential holds); a JSON object is stored as-is,
|
|
69
|
-
e.g. `{"apiKey":"…"}` for an API-key credential. Unset means the actor has no
|
|
70
|
-
upstream credential: `remove` drops one stored at an earlier sign-in.
|
|
71
|
-
|
|
72
|
-
- **Values live in `.env` (or CI secrets), never in `personas.ts` or code.**
|
|
73
|
-
Use a dedicated upstream test account per persona, not a real person's.
|
|
74
|
-
- `read` defaults to `process.env`; a Worker passes `(key) => variables.get(key)`.
|
|
75
|
-
- A malformed JSON value refuses the sign-in with a 500 that names the variable.
|
|
76
|
-
- A delegated token expires upstream like any other; re-signing the actor
|
|
77
|
-
in re-stores whatever the variable holds now.
|
|
78
|
-
|
|
79
|
-
## The same actors sign a human in
|
|
80
|
-
|
|
81
|
-
Declared actors are not only for automated runs. `signInPath` is Better Auth's
|
|
82
|
-
`actor` plugin (see `pikku-auth`, a separate install), which any caller can post to — so the
|
|
83
|
-
frontend gets a one-click "Sign in as …" switcher over the **same** list, and an
|
|
84
|
-
app can be reviewed as each kind of user without anyone knowing a seed password.
|
|
85
|
-
|
|
86
|
-
The switcher holds no credential. It lists personas from
|
|
87
|
-
`/auth/sign-in/personas` and signs in by posting only a persona id to
|
|
88
|
-
`/auth/sign-in/persona`; the server resolves the address. One server piece
|
|
89
|
-
serves both, in the auth config:
|
|
90
|
-
|
|
91
|
-
```ts snippet:personaSignIn
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
It is always open under `pikku dev`. A deployed stage needs actor
|
|
95
|
-
sign-in opted in **and** its `devSwitcher` feature flag on; production never
|
|
96
|
-
has the opt-in, so it lists nobody and refuses every persona sign-in.
|
|
97
|
-
|
|
98
|
-
Do not hand-roll the switcher: `useDevActors()` (`pikku-react`, a separate install) is the logic and
|
|
99
|
-
`<DevActorSwitcher />` from `@pikku/mantine/dev` is a ready rendering of it.
|
|
100
|
-
`pikku fabric validate` **requires** any frontend with a login screen to ship
|
|
101
|
-
one — without it a reviewer is locked out of their own sandbox.
|
|
102
|
-
When the switcher is missing, it is one of three things, and none of them
|
|
103
|
-
errors:
|
|
104
|
-
|
|
105
|
-
- **The list is empty.** On a deployed stage that is the gate
|
|
106
|
-
doing its job — check the opt-in and the `devSwitcher` flag. Locally, check
|
|
107
|
-
the personas declare an `email` (via `scenarios.emailDomain`) and are not
|
|
108
|
-
`runnable: false`.
|
|
109
|
-
- **`personaSignIn` is missing, or the frontend calls another API.** A dev
|
|
110
|
-
proxy (`VITE_API_PROXY`, default `http://localhost:3000`) that points at
|
|
111
|
-
another project's API lists that project's personas, or none.
|
|
112
|
-
- **It is not mounted on the page you are looking at.** The template mounts it
|
|
113
|
-
on the login screen. A public homepage that replaces the `/` → `/app`
|
|
114
|
-
redirect needs its own `<DevActorSwitcher />` in the public layout.
|
|
115
|
-
|
|
116
|
-
When the switcher lists personas but a click 404s, that persona has no `email`
|
|
117
|
-
or is `runnable: false`.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Subscribing to other SSE / WebSocket routes
|
|
2
|
-
|
|
3
|
-
The same `PikkuRealtime` client also handles generic SSE + channel routes (not just
|
|
4
|
-
`/events` topics). Use the path; the base URL is inherited from `PikkuFetch`.
|
|
5
|
-
|
|
6
|
-
```ts
|
|
7
|
-
// Any `sse: true` HTTP route
|
|
8
|
-
const sub = realtime.subscribeToSSE<{ progress: number }>(
|
|
9
|
-
`/workflow-run/${runId}/stream`,
|
|
10
|
-
(event) => setProgress(event.progress)
|
|
11
|
-
)
|
|
12
|
-
// later: sub.close()
|
|
13
|
-
|
|
14
|
-
// Any wireChannel — open a raw socket, wrap in PikkuWebSocket for typed I/O
|
|
15
|
-
const ws = realtime.connectToChannel('/ws/kanban')
|
|
16
|
-
const typed = new PikkuWebSocket<'kanban-live'>(ws)
|
|
17
|
-
typed.getRoute('command').subscribe('message', (data) => {
|
|
18
|
-
/* ... */
|
|
19
|
-
})
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Discover what's available with `pikku meta clients --json` — `channels` and any HTTP
|
|
23
|
-
`sse: true` routes are listed there.
|