@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
|
@@ -101,9 +101,9 @@ export const auth = pikkuBetterAuth(async ({ secrets }) => {
|
|
|
101
101
|
|
|
102
102
|
## ⚠️ Stateless session — ALWAYS enable `cookieCache` for deployed apps
|
|
103
103
|
|
|
104
|
-
By default the CLI wires the **stateful** `betterAuthSession` bridge globally — it calls `services.auth()`, so EVERY unit/worker bundles the full better-auth server (~2.5MB each). On per-unit deploy targets (
|
|
104
|
+
By default the CLI wires the **stateful** `betterAuthSession` bridge globally — it calls `services.auth()`, so EVERY unit/worker bundles the full better-auth server (~2.5MB each). On per-unit deploy targets (Pikku Studio Cloud/Cloudflare) that bloats every bundle and the serial upload phase.
|
|
105
105
|
|
|
106
|
-
Enabling `session: { cookieCache: { enabled: true } }` makes the CLI split out a lean `betterAuthStatelessSession` (`src/scaffold/auth-middleware.gen.ts`) that verifies the signed session cookie using only `BETTER_AUTH_SECRET` — no `services.auth()`, no server bundled. Non-auth units drop from ~2.5MB to ~20KB. Only the auth unit carries the server. `pikku
|
|
106
|
+
Enabling `session: { cookieCache: { enabled: true } }` makes the CLI split out a lean `betterAuthStatelessSession` (`src/scaffold/auth-middleware.gen.ts`) that verifies the signed session cookie using only `BETTER_AUTH_SECRET` — no `services.auth()`, no server bundled. Non-auth units drop from ~2.5MB to ~20KB. Only the auth unit carries the server. `pikku validate` warns (`better-auth-stateless-session-disabled`) when it's off.
|
|
107
107
|
|
|
108
108
|
**Tradeoff:** server-side session revocation isn't seen until the cookie cache expires (sign-out is still immediate — it deletes the cookie).
|
|
109
109
|
|
|
@@ -238,21 +238,20 @@ 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 |
|
|
245
245
|
| ------------------------ | ------------------ | ----------------------------------------------------------------------- | ------------------------------------------------------------- |
|
|
246
246
|
| `pikkuBan()` | `pikku-ban` | `user.banned/banReason/banExpires` | You ban users (the schema + enforcement half of the above) |
|
|
247
|
-
| `
|
|
247
|
+
| `pikkuVirtualUser()` | `virtualUser` | `POST /sign-in/virtual-user`, `user.virtualUser` | Scenarios sign in as a virtual user |
|
|
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
|
-
with better-auth's own and a bare `
|
|
254
|
-
nothing about where it came from. The unprefixed names — `ban`, `
|
|
255
|
-
`credentialOAuth`, `delegatedAuth
|
|
252
|
+
with better-auth's own and a bare `virtualUser()` next to `organization()` says
|
|
253
|
+
nothing about where it came from. The unprefixed names — `ban`, `virtualUser`,
|
|
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
|
|
@@ -343,26 +342,11 @@ an existing user row, so it cannot take over someone else's account.
|
|
|
343
342
|
For an addon generated from an OpenAPI spec, none of this is written by hand:
|
|
344
343
|
`pikku new addon --openapi … --auth-config <file>` generates
|
|
345
344
|
`authenticate<Name>Upstream` in the addon and wires this plugin, the stored
|
|
346
|
-
credential and the
|
|
345
|
+
credential and the virtual user credentials into `src/auth.ts`. The config format is
|
|
347
346
|
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.
|
|
@@ -471,177 +455,166 @@ hostname check — because a one-request path to an admin session is exactly the
|
|
|
471
455
|
thing that must not survive a deploy. An app that has not declared the `admin`
|
|
472
456
|
scope still gets a session, with a warning, since a scopeless dev user is useful.
|
|
473
457
|
|
|
474
|
-
###
|
|
458
|
+
### Virtual user sign-in (`virtualUser` plugin)
|
|
475
459
|
|
|
476
460
|
A different thing from dev quick login, and the one to reach for when "sign in as
|
|
477
461
|
someone" means **a particular kind of user** rather than one fixed admin.
|
|
478
462
|
Register it explicitly — it is not automatic:
|
|
479
463
|
|
|
480
464
|
```typescript
|
|
481
|
-
import {
|
|
465
|
+
import {
|
|
466
|
+
VIRTUAL_USER_SIGN_IN_OPT_IN_ENV,
|
|
467
|
+
pikkuVirtualUser,
|
|
468
|
+
} from '@pikku/better-auth'
|
|
482
469
|
|
|
483
470
|
plugins: [
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
allowSignIn: await variables.get(
|
|
471
|
+
pikkuVirtualUser({
|
|
472
|
+
verifyKey: await variables.get('VIRTUAL_USER_VERIFY_KEY'),
|
|
473
|
+
allowSignIn: await variables.get(VIRTUAL_USER_SIGN_IN_OPT_IN_ENV),
|
|
487
474
|
}),
|
|
488
475
|
]
|
|
489
476
|
```
|
|
490
477
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
478
|
+
There is one door, and two ways through it.
|
|
479
|
+
|
|
480
|
+
- **A run signs in from inside the app.** A scheduled virtual user run calls
|
|
481
|
+
`auth.api.signInVirtualUserInternal`, which is `SERVER_ONLY`: it exists on
|
|
482
|
+
`auth.api` and answers 404 through `auth.handler`, so no HTTP caller can reach
|
|
483
|
+
it. The run takes the cookie and then drives the app over HTTP.
|
|
484
|
+
- **An outside caller presents one signed statement.** `pikku dev`, `pikku
|
|
485
|
+
scenario run`, `pikku virtual-user run`, `pikku pages screenshot --as` and the
|
|
486
|
+
Playwright provider `POST ${basePath}/sign-in/virtual-user` `{ statement }` →
|
|
487
|
+
200 + the normal session cookie. The statement is an EdDSA JWT with `sub` (the
|
|
488
|
+
virtual user id), `aud` (the app's origin), a short expiry (180 seconds by
|
|
489
|
+
default, 300 at most) and a one-time `jti`. The plugin verifies it against
|
|
490
|
+
`verifyKey` with a verify-only service; a replayed `jti` is refused. The replay
|
|
491
|
+
record is in memory, so it is per process.
|
|
492
|
+
|
|
493
|
+
**Keys.** `pikku dev` generates a key pair under
|
|
494
|
+
`<runtimeDir>/virtual-user/signing.key` (mode 0600, next to a `.gitignore` of
|
|
495
|
+
`*`) and gives the app the public half, so local development needs no
|
|
496
|
+
configuration. A deployed stage has one key pair: the deployer holds the private
|
|
497
|
+
key (`VIRTUAL_USER_SIGNING_KEY`) and the app reads the public key from
|
|
498
|
+
`VIRTUAL_USER_VERIFY_KEY`. A stage without a verify key refuses statements and
|
|
499
|
+
logs why; it never falls back to anything weaker.
|
|
500
|
+
|
|
501
|
+
**Which command is running decides whether it works.** `pikku dev` sets
|
|
502
|
+
`PIKKU_DEV_VIRTUAL_USER_SIGN_IN`. Everywhere else the endpoint refuses
|
|
503
|
+
(`VirtualUser sign-in is disabled outside \`pikku dev\``) — `pikku serve` clears the
|
|
504
|
+
marker outright. In production neither endpoint is registered at all.
|
|
514
505
|
|
|
515
506
|
A stage that genuinely must run scenarios opts in on purpose, with
|
|
516
|
-
`
|
|
507
|
+
`PIKKU_ALLOW_VIRTUAL_USER_SIGN_IN=passwordless-virtual-user-sign-in`. Any other value is
|
|
517
508
|
ignored and warned about, so the hatch cannot be opened by copying a `true` from
|
|
518
509
|
the line above.
|
|
519
510
|
|
|
520
511
|
**Pass it in on any runtime without a populated `process.env`.** The gate reads
|
|
521
512
|
the environment by default, which is enough for Node but not for a Worker: there
|
|
522
513
|
the opt-in arrives as a binding and reaches user code through the variables
|
|
523
|
-
service
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
what opens the gate is still something the deployment set and an operator can
|
|
528
|
-
read back out of it, never something compiled into the bundle. A value passed
|
|
529
|
-
here is the one consulted, so the environment cannot quietly override what the
|
|
530
|
-
stage was configured with.
|
|
514
|
+
service. `allowSignIn` takes the value the caller already read —
|
|
515
|
+
`await variables.get(VIRTUAL_USER_SIGN_IN_OPT_IN_ENV)` — and is checked against the same
|
|
516
|
+
literal, near-miss warning included. A value passed here is the one consulted, so
|
|
517
|
+
the environment cannot quietly override what the stage was configured with.
|
|
531
518
|
|
|
532
519
|
**Signing in and provisioning are separate powers.** An unknown address becomes
|
|
533
|
-
|
|
534
|
-
in as the
|
|
535
|
-
everything else (`No
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
persona.** Provisioning grants declared roles to actor accounts, so an
|
|
543
|
-
`admin` persona is an actor holding real admin — anyone with the secret _and_ the
|
|
544
|
-
opt-in can take a session as one. Do not treat "actors only" as a licence to open
|
|
545
|
-
the hatch in production.
|
|
520
|
+
a `virtualUser: true` row only under `pikku dev`. With the opt-in set, a stage signs
|
|
521
|
+
in as the virtual users the deployment provisioned when it started and refuses
|
|
522
|
+
everything else (`No virtual user account exists for that address`), so holding the
|
|
523
|
+
signing key on such a stage does not let anyone invent identities.
|
|
524
|
+
|
|
525
|
+
**The signing key is as powerful as the most privileged virtual user.** Provisioning
|
|
526
|
+
grants declared roles to virtual user accounts, so an `admin` virtual user holds
|
|
527
|
+
real admin — anyone with the private key _and_ the opt-in can take a session as one.
|
|
528
|
+
Keep it with the deployer; the app only ever needs the public half.
|
|
546
529
|
|
|
547
530
|
Within that boundary, three properties bound the damage:
|
|
548
531
|
|
|
549
|
-
- **It only ever signs in
|
|
532
|
+
- **It only ever signs in virtual users.** The plugin adds a `user.virtualUser` boolean
|
|
550
533
|
column; an email matching a row without it is refused with `User is not an
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
so a local scenario declaring a new persona needs no seed step. Anywhere else
|
|
534
|
+
virtual user`. So a statement cannot take over a **real user's** account.
|
|
535
|
+
- **Unknown emails are created only under `pikku dev`**, flagged `virtualUser: true`,
|
|
536
|
+
so a local scenario declaring a new virtual user needs no seed step. Anywhere else
|
|
555
537
|
the account has to have been provisioned at boot first.
|
|
556
|
-
- **A
|
|
557
|
-
|
|
558
|
-
paragraph above. The comparison is constant-time and length-hiding, so a wrong
|
|
559
|
-
credential leaks neither the length nor a prefix of the right one.
|
|
538
|
+
- **A statement is bound to one virtual user, one app and a few minutes**, and can
|
|
539
|
+
be used once, so a leaked one is a single short-lived session.
|
|
560
540
|
|
|
561
|
-
This is the endpoint `pikku scenario` signs its
|
|
562
|
-
|
|
563
|
-
id to `/sign-in/
|
|
564
|
-
`
|
|
565
|
-
`pikku-scenario` for the setup
|
|
541
|
+
This is the endpoint `pikku scenario` signs its virtual users in through. The frontend
|
|
542
|
+
does not use it: it posts a virtual user
|
|
543
|
+
id to `/sign-in/switch-virtual-user`, served by
|
|
544
|
+
`pikkuVirtualUser({ virtualUserSignIn: { virtualUsers } })` with no credential — see
|
|
545
|
+
`pikku-scenario` for the setup.
|
|
566
546
|
|
|
567
|
-
### Provisioning
|
|
547
|
+
### Provisioning virtual users
|
|
568
548
|
|
|
569
|
-
Anywhere but `pikku dev`, the accounts have to exist before anyone signs in.
|
|
570
|
-
|
|
549
|
+
Anywhere but `pikku dev`, the accounts have to exist before anyone signs in.
|
|
550
|
+
`provisionVirtualUsers` creates them from the generated virtual users:
|
|
571
551
|
|
|
572
552
|
```ts
|
|
573
|
-
import {
|
|
553
|
+
import { provisionVirtualUsers } from '@pikku/better-auth'
|
|
574
554
|
import {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
} from '#pikku/pikku-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
personas: {
|
|
584
|
-
personas: personaConfigs,
|
|
585
|
-
environments: personaEnvironments,
|
|
586
|
-
},
|
|
587
|
-
})
|
|
555
|
+
virtualUserConfigs,
|
|
556
|
+
virtualUserEnvironments,
|
|
557
|
+
} from '#pikku/pikku-virtual-users.gen.js'
|
|
558
|
+
|
|
559
|
+
await provisionVirtualUsers(
|
|
560
|
+
{ auth, scopeService, logger },
|
|
561
|
+
{ virtualUsers: virtualUserConfigs, environments: virtualUserEnvironments }
|
|
562
|
+
)
|
|
588
563
|
```
|
|
589
564
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
declaration and looks again. On a stage that
|
|
593
|
-
one query, and the pass only runs when there
|
|
594
|
-
create.
|
|
565
|
+
`auth` only needs to resolve `{ $context }`, so the singleton `services.auth`
|
|
566
|
+
works as is. Call it from whatever route resolves the address a caller wants to
|
|
567
|
+
act as: a miss provisions the declaration and looks again. On a stage that
|
|
568
|
+
already holds the virtual user that is one query, and the pass only runs when there
|
|
569
|
+
is genuinely something absent to create.
|
|
595
570
|
|
|
596
571
|
**Do not reach for `pikkuServerLifecycle`'s `afterStart` for this.** That hook is
|
|
597
572
|
invoked by `pikku serve` and `pikku dev` and by nothing else — no deploy runtime
|
|
598
573
|
calls it — so a stage on Workers or a serverless target that provisioned from
|
|
599
|
-
`afterStart` provisioned nothing, and every
|
|
574
|
+
`afterStart` provisioned nothing, and every virtual user signed in holding no roles.
|
|
600
575
|
|
|
601
576
|
Provisioning runs where the database already is, which is the point: the CLI has
|
|
602
577
|
no connection to a deployed environment's database — it resolves one from the
|
|
603
|
-
local project config — so a `pikku
|
|
604
|
-
write them to whatever database the checkout happened to point at. `pikku
|
|
578
|
+
local project config — so a `pikku virtual-user sync staging` that wrote rows would
|
|
579
|
+
write them to whatever database the checkout happened to point at. `pikku virtual-user
|
|
605
580
|
sync <environment>` still exists, and reports who that environment will provision
|
|
606
581
|
and why anyone was skipped, which is what you run _before_ the deploy.
|
|
607
582
|
|
|
608
|
-
It creates missing accounts as `
|
|
583
|
+
It creates missing accounts as `virtualUser: true`, applies the roles each virtual user
|
|
609
584
|
declares, and is additive — it never revokes. `PIKKU_ENV` (or an explicit
|
|
610
585
|
`environment`) selects who is eligible, through the same rule that decides who
|
|
611
|
-
may run there; an address already held by a real, non-
|
|
612
|
-
than being granted the
|
|
586
|
+
may run there; an address already held by a real, non-virtual-user user throws rather
|
|
587
|
+
than being granted the virtual user's roles.
|
|
613
588
|
|
|
614
|
-
**Deleting a
|
|
615
|
-
the account keeps every role it was granted, and the
|
|
616
|
-
on the `
|
|
617
|
-
|
|
589
|
+
**Deleting a virtual user does not delete its account.** Being additive leaves a hole:
|
|
590
|
+
the account keeps every role it was granted, and the virtual user endpoint authenticates
|
|
591
|
+
on the `virtualUser` column alone without consulting the declaration — so an `admin`
|
|
592
|
+
virtual user nobody declares any more is still a live way in wherever that endpoint is
|
|
618
593
|
open. By default provisioning warns about those accounts and changes nothing.
|
|
619
594
|
`orphans: 'ban'` shuts them:
|
|
620
595
|
|
|
621
596
|
```ts
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
personas: personaConfigs,
|
|
628
|
-
environments: personaEnvironments,
|
|
597
|
+
await provisionVirtualUsers(
|
|
598
|
+
{ auth, scopeService, logger },
|
|
599
|
+
{
|
|
600
|
+
virtualUsers: virtualUserConfigs,
|
|
601
|
+
environments: virtualUserEnvironments,
|
|
629
602
|
orphans: 'ban',
|
|
630
|
-
}
|
|
631
|
-
|
|
603
|
+
}
|
|
604
|
+
)
|
|
632
605
|
```
|
|
633
606
|
|
|
634
607
|
It writes the same `banned` column the console's ban RPC writes (so it needs the
|
|
635
608
|
`pikkuBan()` plugin wired, and says so if it isn't), revokes the account's sessions,
|
|
636
609
|
and leaves the row, its grants and its history intact — provisioning lifts the
|
|
637
|
-
ban again by itself if the
|
|
638
|
-
offered:
|
|
610
|
+
ban again by itself if the virtual user comes back. Deleting is deliberately not
|
|
611
|
+
offered: a virtual user row is referenced by whatever those scenarios did while it
|
|
639
612
|
existed.
|
|
640
613
|
|
|
641
614
|
`report` is the default because a rolling deploy runs the new replica's
|
|
642
615
|
provisioning while the old replica is still serving, so for the length of that
|
|
643
|
-
overlap "no
|
|
644
|
-
A
|
|
616
|
+
overlap "no virtual user claims this" is a statement about the newer declaration only.
|
|
617
|
+
A virtual user pinned to another environment counts as unclaimed here — it has no
|
|
645
618
|
business holding a signable account in an environment its own rule refuses it.
|
|
646
619
|
|
|
647
620
|
---
|
|
@@ -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
|
|
|
@@ -3,14 +3,16 @@ name: pikku-build
|
|
|
3
3
|
description: >-
|
|
4
4
|
Use to build on Pikku — turning a fresh scaffold into a working app (quick spike, real product,
|
|
5
5
|
or a showcase that exercises every surface), adding a feature to an app that already exists, and
|
|
6
|
-
the one-off cleanup right after a template is cloned. Covers the knowledge base,
|
|
7
|
-
roles, filing the work as changes
|
|
8
|
-
deploying. TRIGGER when: the user asks for an app to be built on
|
|
9
|
-
project needs turning into a product, the user asks to add a feature
|
|
10
|
-
in a working app, or a template was just cloned or scaffolded. DO NOT
|
|
11
|
-
asks for a one-off edit to an existing function, asks about Pikku concepts
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
the one-off cleanup right after a template is cloned. Covers the knowledge base, virtual users and
|
|
7
|
+
roles, filing the work as changes, the scenario that proves each one, theming, multi-app
|
|
8
|
+
layouts and deploying. TRIGGER when: the user asks for an app to be built on
|
|
9
|
+
Pikku, a freshly scaffolded project needs turning into a product, the user asks to add a feature
|
|
10
|
+
or wire up a new endpoint in a working app, or a template was just cloned or scaffolded. DO NOT
|
|
11
|
+
TRIGGER when: the user asks for a one-off edit to an existing function, asks about Pikku concepts
|
|
12
|
+
(use pikku-concepts), wants one specific surface explained rather than built (use that surface's
|
|
13
|
+
skill), only needs the technical plan for one claimed changeset (use pikku-architect), or is
|
|
14
|
+
working items off a deployed stage's changes queue (use pikku-changes).
|
|
15
|
+
allowed-tools: Bash(yarn pikku meta *), Bash(yarn pikku all *), Bash(yarn tsc), Bash(git status *), Bash(git diff *), Bash(git switch *), Bash(git checkout *), Bash(git checkout -b *), Bash(git add *), Bash(git commit *), Bash(git rm *), Bash(git mv *), Bash(git log *), Bash(git branch *), Bash(yarn pikku cloud report *), Bash(npx --no pikku cloud report *)
|
|
14
16
|
argument-hint: '[feature description]'
|
|
15
17
|
installGroups: [core]
|
|
16
18
|
agent:
|
|
@@ -30,29 +32,30 @@ agent:
|
|
|
30
32
|
|
|
31
33
|
## Which mode
|
|
32
34
|
|
|
33
|
-
| The situation
|
|
34
|
-
|
|
|
35
|
-
| A template was just cloned or scaffolded, and the tree still looks like one
|
|
36
|
-
| A real product, meant to be picked up by someone else
|
|
37
|
-
| A spike, a throwaway demo, an idea nobody has committed to
|
|
38
|
-
| A showcase meant to exercise every Pikku surface
|
|
39
|
-
| A feature added to an app that already has its knowledge base
|
|
35
|
+
| The situation | Read |
|
|
36
|
+
| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
|
|
37
|
+
| A template was just cloned or scaffolded, and the tree still looks like one | `references/post-clone.md` first, then come back |
|
|
38
|
+
| A real product, meant to be picked up by someone else | `references/app.md` — the default |
|
|
39
|
+
| A spike, a throwaway demo, an idea nobody has committed to | `references/quick.md` |
|
|
40
|
+
| A showcase meant to exercise every Pikku surface | `references/platform.md`, read together with `references/app.md` |
|
|
41
|
+
| A feature added to an app that already has its knowledge base | `references/feature.md` |
|
|
42
|
+
| Writing or fixing the scenarios that prove a changeset (app §7, §7a) | `references/scenarios.md` |
|
|
43
|
+
| Before the first screen is built: a picture of the screens, a design direction | `references/design.md` |
|
|
44
|
+
| Authoring or changing the theme (app §8a) | `references/theming.md` |
|
|
45
|
+
| A screen needs data no function returns yet | `references/mocks.md` |
|
|
46
|
+
| Adding a second frontend (app §4), at the changeset that needs it | `references/multi-app.md` |
|
|
47
|
+
| Shipping an app as a desktop or Android app | `references/native-app.md` |
|
|
48
|
+
| Deploying, and the deploy-readiness contract (app §9) | `references/ship.md` |
|
|
49
|
+
| The request is built on an OpenAPI spec (auth mode, sign-in or connect screen) | `references/openapi.md` |
|
|
40
50
|
|
|
41
51
|
**App is the default.** A small or toy-sounding app does not make it Quick;
|
|
42
52
|
only an explicit signal of speed or throwaway-ness does. Platform is not "App
|
|
43
|
-
plus more effort" — it is App plus a deliberate surface checklist
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
a picture of the screens first, committing to a design direction, and judging
|
|
50
|
-
whether the screens realise it — read before the first screen is built, not
|
|
51
|
-
after the last), `references/theming.md`
|
|
52
|
-
(authoring the theme),
|
|
53
|
-
`references/ship.md` (deploying, and the Fabric-readiness contract),
|
|
54
|
-
`references/openapi.md` (an app on an OpenAPI spec: the auth mode, the
|
|
55
|
-
auth-config format, and the sign-in or connect screen it implies).
|
|
53
|
+
plus more effort" — it is App plus a deliberate surface checklist: read both
|
|
54
|
+
files, follow the base in full, and do not blend the two into one plan.
|
|
55
|
+
|
|
56
|
+
Each reference names the topics it leans on but never tells you to open
|
|
57
|
+
another file; this table is the only routing. Open a reference when its row
|
|
58
|
+
matches, not up front.
|
|
56
59
|
|
|
57
60
|
## Bootstrap before anything else
|
|
58
61
|
|
|
@@ -152,11 +155,11 @@ generated functions through `ref()`.
|
|
|
152
155
|
|
|
153
156
|
Whenever pikku or a skill costs you time — a command that failed on a fresh
|
|
154
157
|
tree, a skill that described a flag the CLI does not have, generated code you
|
|
155
|
-
had to fix by hand — file it then
|
|
156
|
-
`pikku-report` skill has the fields. Leave out secrets, tokens and customer data.
|
|
158
|
+
had to fix by hand — file it then, the way the
|
|
159
|
+
`pikku-report` skill describes. That skill has the fields. Leave out secrets, tokens and customer data.
|
|
157
160
|
|
|
158
161
|
Findings are held until hand-over. The last thing in the hand-over, after the
|
|
159
|
-
app runs (and is deployed, if they chose to), is `pikku
|
|
162
|
+
app runs (and is deployed, if they chose to), is the `pikku-report` send step: if it
|
|
160
163
|
lists findings and asks, ask the user — Yes, No, Always or Never — and run it
|
|
161
164
|
again with `--consent <answer>`. If it says reporting is off, do not ask.
|
|
162
165
|
|
|
@@ -168,8 +171,8 @@ build makes or changes something the console can show, give the
|
|
|
168
171
|
`http://localhost:<port>/console/...` link instead of describing it.
|
|
169
172
|
|
|
170
173
|
Until the app is deployed that is the local open-source console, on the port
|
|
171
|
-
`pikku dev` printed. Once it is
|
|
172
|
-
you are talking about instead
|
|
174
|
+
`pikku dev` printed. Once it is deployed, link the hosted console for the stage
|
|
175
|
+
you are talking about instead.
|
|
173
176
|
|
|
174
177
|
| Level | Links | Code in the conversation |
|
|
175
178
|
| ------------------ | --------------------------- | ------------------------ |
|
|
@@ -185,7 +188,7 @@ words and link to where they can see it.
|
|
|
185
188
|
| Shows | Path |
|
|
186
189
|
| --------------------- | -------------------------------------------------------------------------- |
|
|
187
190
|
| Knowledge, plans | `/console/knowledge`, `/console/knowledge?id=<note path>` |
|
|
188
|
-
|
|
|
191
|
+
| Virtual users | `/console/virtual-users`, `/console/virtual-users?virtual user=<id>` |
|
|
189
192
|
| Roles and permissions | `/console/roles`, `/console/scopes` (only with `@pikku/addon-admin` wired) |
|
|
190
193
|
| Scenarios and runs | `/console/scenarios?id=<id>`, `/console/scenarios?view=runs&run=<run id>` |
|
|
191
194
|
| Workflows | `/console/workflow?id=<id>` |
|