@pikku/cli 0.12.85 → 0.12.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/console-app/assets/{index-CEv-kj3J.js → index-Cr3_cO3Z.js} +161 -147
  2. package/console-app/index.html +1 -1
  3. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  4. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  5. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  6. package/dist/.pikku/cli/pikku-cli-channel.js +1 -1
  7. package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +1 -1
  8. package/dist/.pikku/cli/pikku-cli-client.gen.js +1 -1
  9. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
  10. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
  11. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.json +4 -0
  12. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  13. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  14. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  15. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +4 -0
  16. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  17. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  18. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  19. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  20. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  21. package/dist/.pikku/function/pikku-function-types.gen.d.ts +1 -1
  22. package/dist/.pikku/function/pikku-function-types.gen.js +1 -1
  23. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  24. package/dist/.pikku/function/pikku-functions-meta.gen.json +39 -15
  25. package/dist/.pikku/function/pikku-functions.gen.js +3 -1
  26. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  27. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  28. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  29. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  30. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  31. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  32. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  33. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  34. package/dist/.pikku/pikku-services.gen.d.ts +2 -1
  35. package/dist/.pikku/pikku-services.gen.js +1 -0
  36. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  37. package/dist/.pikku/pikku-types.gen.js +1 -1
  38. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  39. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  40. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  41. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +1 -0
  42. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  43. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  44. package/dist/.pikku/schemas/register.gen.js +3 -1
  45. package/dist/.pikku/schemas/schemas/FabricLoginInput.schema.json +1 -1
  46. package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
  47. package/dist/.pikku/schemas/schemas/PikkuUserAdminFunctionsOutput.schema.json +1 -0
  48. package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +1 -1
  49. package/dist/.pikku/scopes/pikku-scope-types.gen.js +1 -1
  50. package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
  51. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +1 -1
  52. package/dist/.pikku/secrets/pikku-secret-types.gen.js +1 -1
  53. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  54. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  55. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  56. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  57. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +1 -1
  58. package/dist/.pikku/variables/pikku-variable-types.gen.js +1 -1
  59. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  60. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  61. package/dist/.pikku/workflow/meta/allWorkflow.gen.json +8 -2
  62. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +1 -1
  63. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +1 -1
  64. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  65. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  66. package/dist/bin/pikku-bin.mjs +2 -2
  67. package/dist/src/fabric/fabric-commands.d.ts +6 -3
  68. package/dist/src/fabric/fabric-commands.js +4 -0
  69. package/dist/src/fabric/functions/llm-key.function.d.ts +4 -4
  70. package/dist/src/fabric/functions/login.function.d.ts +4 -0
  71. package/dist/src/fabric/functions/login.function.js +45 -4
  72. package/dist/src/functions/wirings/ai-agent/pikku-command-public-agent.js +6 -2
  73. package/dist/src/functions/wirings/ai-agent/serialize-public-agent.d.ts +5 -1
  74. package/dist/src/functions/wirings/ai-agent/serialize-public-agent.js +81 -48
  75. package/dist/src/functions/wirings/auth/pikku-command-auth.js +4 -0
  76. package/dist/src/functions/wirings/console/pikku-command-console-functions.js +6 -2
  77. package/dist/src/functions/wirings/console/serialize-console-functions.d.ts +5 -1
  78. package/dist/src/functions/wirings/console/serialize-console-functions.js +55 -23
  79. package/dist/src/functions/wirings/functions/schemas.js +10 -1
  80. package/dist/src/functions/wirings/graph/pikku-command-graph-wirings.js +2 -0
  81. package/dist/src/functions/wirings/realtime/pikku-command-events-scaffold.js +8 -2
  82. package/dist/src/functions/wirings/realtime/serialize-events-scaffold.d.ts +5 -4
  83. package/dist/src/functions/wirings/realtime/serialize-events-scaffold.js +17 -7
  84. package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.js +6 -2
  85. package/dist/src/functions/wirings/rpc/pikku-command-remote-rpc.js +6 -2
  86. package/dist/src/functions/wirings/rpc/serialize-public-rpc.d.ts +5 -1
  87. package/dist/src/functions/wirings/rpc/serialize-public-rpc.js +16 -5
  88. package/dist/src/functions/wirings/rpc/serialize-remote-rpc.d.ts +5 -1
  89. package/dist/src/functions/wirings/rpc/serialize-remote-rpc.js +16 -5
  90. package/dist/src/functions/wirings/scenarios/pikku-command-scenario-functions.js +8 -2
  91. package/dist/src/functions/wirings/scenarios/serialize-scenario-functions.d.ts +5 -1
  92. package/dist/src/functions/wirings/scenarios/serialize-scenario-functions.js +22 -16
  93. package/dist/src/functions/wirings/user-admin/pikku-command-user-admin-functions.d.ts +1 -0
  94. package/dist/src/functions/wirings/user-admin/pikku-command-user-admin-functions.js +49 -0
  95. package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.d.ts +24 -0
  96. package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.js +283 -0
  97. package/dist/src/functions/wirings/webhook/pikku-command-webhook.js +6 -2
  98. package/dist/src/functions/wirings/webhook/serialize-webhook.d.ts +5 -8
  99. package/dist/src/functions/wirings/webhook/serialize-webhook.js +19 -12
  100. package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.js +8 -2
  101. package/dist/src/functions/wirings/workflow/serialize-workflow-routes.d.ts +5 -1
  102. package/dist/src/functions/wirings/workflow/serialize-workflow-routes.js +61 -31
  103. package/dist/src/functions/workflows/all.workflow.js +8 -0
  104. package/dist/src/utils/pikku-cli-config.js +40 -10
  105. package/dist/src/utils/remove-legacy-scaffold-file.d.ts +3 -0
  106. package/dist/src/utils/remove-legacy-scaffold-file.js +43 -0
  107. package/dist/src/utils/serialize-schemas.js +57 -2
  108. package/dist/tsconfig.tsbuildinfo +1 -1
  109. package/package.json +5 -5
  110. package/skills/pikku-addon/SKILL.md +1 -0
  111. package/skills/pikku-ai-agent/SKILL.md +2 -1
  112. package/skills/pikku-ai-vercel/SKILL.md +1 -0
  113. package/skills/pikku-better-auth/SKILL.md +57 -0
  114. package/skills/pikku-concepts/SKILL.md +1 -1
  115. package/skills/pikku-concepts/references/concept-mapping.md +11 -9
  116. package/skills/pikku-emails/SKILL.md +1 -0
  117. package/skills/pikku-fabric-debug/SKILL.md +112 -0
  118. package/skills/pikku-permissions/SKILL.md +8 -8
  119. package/skills/pikku-react/SKILL.md +32 -3
  120. package/skills/pikku-react-query/SKILL.md +38 -1
  121. package/skills/pikku-realtime/SKILL.md +1 -1
  122. package/skills/pikku-security/SKILL.md +3 -3
  123. package/skills/pikku-template-clone/SKILL.md +1 -0
  124. package/cli.schema.json +0 -1
@@ -9,6 +9,7 @@ description: >-
9
9
  user asks about ANY form of authentication, login, logout, sessions, or user identity — always
10
10
  answer with this skill. DO NOT TRIGGER when: user asks about JWT middleware (use pikku-security)
11
11
  or custom session services (use pikku-services).
12
+ installGroups: [core]
12
13
  ---
13
14
 
14
15
  # Pikku Better Auth Integration
@@ -119,6 +120,62 @@ Enabling `session: { cookieCache: { enabled: true } }` makes the CLI split out a
119
120
 
120
121
  In both cases a **route-scoped** registration (`addHTTPMiddleware('/some/path', [...])`) does NOT count — only a global one suppresses the generated default. The generated middleware in a `.gen.ts` file is also ignored by the detector, so regeneration never self-suppresses.
121
122
 
123
+ ### Admin capabilities are scopes, not a role
124
+
125
+ Pikku does **not** use better-auth's `admin()` plugin, and nothing in this
126
+ package reads a `role` column. A role is not a permission: "who may impersonate"
127
+ and "who may rebind a shared credential" are different capabilities one user can
128
+ hold independently, which a single `role` string cannot express. Every gate the
129
+ package owns therefore resolves the caller's scopes through the registered
130
+ `ScopeService` and checks the `admin:*` tree:
131
+
132
+ | Gate | Scope required |
133
+ | --- | --- |
134
+ | `impersonation` (`betterAuthSession` / `betterAuthStatelessSession`) | `admin:impersonate` |
135
+ | `credentialOAuth`'s `canLinkSingleton` | `admin:credentials:link` |
136
+ | the console's user directory | `admin:users:list` |
137
+
138
+ Holding the bare `admin` scope satisfies all of them — a parent grant covers
139
+ everything nested beneath it — so `admin` is the direct replacement for the old
140
+ `role === 'admin'`.
141
+
142
+ Declare the tree in your own `wireScope` (the CLI extracts it by AST, so it must
143
+ be an inline literal; `ADMIN_SCOPE_TREE` is exported from `@pikku/better-auth`
144
+ as the reference shape). Apps wiring `@pikku/addon-console` inherit it already.
145
+
146
+ ```typescript
147
+ wireScope({
148
+ admin: {
149
+ displayName: 'Administration',
150
+ description: 'Capabilities that act on the application as a whole',
151
+ scopes: {
152
+ impersonate: { description: 'Act as another user' },
153
+ credentials: {
154
+ description: 'Application-wide credentials',
155
+ scopes: {
156
+ link: { description: 'Bind a shared credential for every user' },
157
+ },
158
+ },
159
+ users: {
160
+ description: 'The user directory',
161
+ scopes: { list: { description: 'List and search users' } },
162
+ },
163
+ },
164
+ },
165
+ })
166
+ ```
167
+
168
+ Then grant it — via a role (`scopeService.createRole({ name: 'admin', scopes: ['admin'] })` plus `addUserToRole`) or directly with `addScopeToUser`.
169
+
170
+ Every gate **fails closed**: with no `ScopeService` registered nothing can hold
171
+ a scope, so nothing is authorized, and the denial is logged at `warn` because
172
+ that is a configuration bug rather than a permissions decision. Pass your own
173
+ `canImpersonate` / `canLinkSingleton` to override the default entirely.
174
+
175
+ Sibling concerns — banning a user, listing users from your own screens — are
176
+ actions your app *invokes*, not things pikku gates. Put them on your own
177
+ functions with `scopes: ['admin:users:ban']` and friends.
178
+
122
179
  ### 2. Production database adapter
123
180
 
124
181
  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.
@@ -71,7 +71,7 @@ const updateTodo = pikkuFunc({
71
71
  input: UpdateTodoInput,
72
72
  output: TodoOutput,
73
73
  func: async (services, data, wire) => {
74
- const session = await wire.session.get()
74
+ const { session } = wire
75
75
  return services.todoStore.update(data.id, data)
76
76
  },
77
77
  })
@@ -192,17 +192,19 @@ router.delete('/users/:id', requireRole('admin'), deleteUser)
192
192
  **Pikku:**
193
193
 
194
194
  ```typescript
195
- const isAdmin = pikkuPermission(async (services, data, wire) => {
196
- const session = await wire.session.get()
197
- return session?.role === 'admin'
195
+ const isOwner = pikkuPermission(async ({ db }, { userId }, wire) => {
196
+ const { session } = wire
197
+ return session?.userId === userId
198
198
  })
199
199
 
200
- // Declare on the function definition (the only place permissions live)
200
+ // Declare on the function definition (the only place permissions live).
201
+ // A capability like "may delete users" is a scope, not a permission.
201
202
  export const deleteUser = pikkuFunc({
202
203
  func: async (services, data) => {
203
204
  /* ... */
204
205
  },
205
- permissions: { admin: [isAdmin] },
206
+ scopes: ['admin:users:delete'],
207
+ permissions: { owner: [isOwner] },
206
208
  })
207
209
 
208
210
  // App-wide baseline every function must also pass (AND gate, narrow-only)
@@ -476,7 +478,7 @@ const updateTodo = pikkuFunc(async (services, { id, title }, wire) => {
476
478
  const todo = services.todoStore.getTodo(id)
477
479
  if (!todo) throw new NotFoundError('Todo not found')
478
480
 
479
- const session = await wire.session.get()
481
+ const { session } = wire
480
482
  if (todo.userId !== session.userId) throw new ForbiddenError()
481
483
 
482
484
  return { todo: services.todoStore.update(id, { title }) }
@@ -509,18 +511,18 @@ const login = pikkuSessionlessFunc(
509
511
  async ({ jwt }, { username, password }, wire) => {
510
512
  const user = authenticate(username, password)
511
513
  const token = await jwt.sign({ userId: user.id })
512
- await wire.session.set({ userId: user.id, user }) // Set
514
+ await wire.setSession({ userId: user.id, user }) // Set
513
515
  return { token, user }
514
516
  }
515
517
  )
516
518
 
517
519
  const getMe = pikkuFunc(async (services, data, wire) => {
518
- const session = await wire.session.get() // Get
520
+ const { session } = wire // Get
519
521
  return { user: session.user }
520
522
  })
521
523
 
522
524
  const logout = pikkuFunc(async (services, data, wire) => {
523
- await wire.session.clear() // Clear
525
+ await wire.clearSession() // Clear
524
526
  return { success: true }
525
527
  })
526
528
  ```
@@ -10,6 +10,7 @@ description: >-
10
10
  email (verification, password reset, invitation, receipt), wire email sending, or translate an
11
11
  email. DO NOT TRIGGER when: user asks about i18n for the app UI (use pikku-i18n) or auth flows
12
12
  in general (use pikku-better-auth).
13
+ installGroups: [core]
13
14
  ---
14
15
 
15
16
  # Pikku Emails
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: pikku-fabric-debug
3
+ description: 'Debug a deployed Fabric stage from the CLI — read logs, find recent errors, follow a single request end-to-end by traceId, and check request/error/latency metrics. TRIGGER when: a deployed Fabric app is erroring, timing out, or behaving differently than local; the user asks "why is prod failing", "check the logs", "what happened to this request"; or a deploy succeeded but the app misbehaves. DO NOT TRIGGER when: the failure reproduces locally (debug it locally), the deploy itself failed (use pikku-fabric — that is a build/config problem, not a runtime one), or the project is not deployed to Fabric.'
4
+ installGroups: [fabric]
5
+ ---
6
+
7
+ # Debugging a deployed Fabric stage
8
+
9
+ ## Agent Operating Procedure
10
+
11
+ Use this skill as an execution checklist, not reference material.
12
+
13
+ 1. Reproduce locally first. If it fails locally too, debug it there — the
14
+ deployed stage adds cost and latency to every iteration.
15
+ 2. Start from `errors`, not `logs`. Errors are already filtered and carry the
16
+ traceId that unlocks the rest.
17
+ 3. Follow one trace end-to-end before forming a theory. A single failing request
18
+ tells you more than a hundred unrelated log lines.
19
+ 4. Fix the source cause and redeploy. Never leave the diagnosis at "it is flaky".
20
+ 5. Confirm the fix against the same stage — recheck `errors` for the function.
21
+
22
+ Every command below requires a logged-in CLI and a linked project. Both fail
23
+ with the exact remediation if not:
24
+
25
+ ```
26
+ Not logged in. Run `pikku fabric login` first.
27
+ No fabric project linked. Run `pikku fabric link` first.
28
+ ```
29
+
30
+ ## The loop
31
+
32
+ **1 — What is broken?**
33
+
34
+ ```bash
35
+ pikku fabric errors -b main # branch defaults to main
36
+ pikku fabric errors -b main --function createOrder
37
+ ```
38
+
39
+ Prints a `WHEN | FUNCTION | TRACE | MESSAGE` table. The message is **truncated
40
+ to 100 characters** — treat it as a label, not the full error. The TRACE column
41
+ is the input to the next step.
42
+
43
+ **2 — What happened in that one request?**
44
+
45
+ ```bash
46
+ pikku fabric trace <traceId> -b main
47
+ pikku fabric trace <traceId> -b main --json
48
+ ```
49
+
50
+ `--branch` is **required** here (no default). Each event prints as:
51
+
52
+ ```
53
+ <timestamp> <scriptName> <wireType>:<wireId> <duration>ms — <error|message|outcome>
54
+ ```
55
+
56
+ This is the whole request across the stage — every unit it touched, in order,
57
+ with per-event durations. The last event before the failure is where to look.
58
+
59
+ **3 — Is it one request or the whole stage?**
60
+
61
+ ```bash
62
+ pikku fabric metrics -b main # last 24h
63
+ pikku fabric metrics -b main --hours 2 --function createOrder
64
+ ```
65
+
66
+ Rows are `reqs= err= (rate%) avg= min= max=` per bucket. A single bad request
67
+ with a healthy error rate is a data problem; a climbing error rate is a
68
+ deployment or dependency problem. `--json` additionally returns a `wireTypes`
69
+ breakdown (requests per http/queue/scheduler/…) that the table output omits.
70
+
71
+ **4 — Wider context around the failure**
72
+
73
+ ```bash
74
+ pikku fabric logs -b main
75
+ pikku fabric logs -b main --level warn
76
+ pikku fabric logs -b main -f # follow
77
+ ```
78
+
79
+ `--branch` is **required** — `logs` throws `Specify --branch <branch-name>.`
80
+ without it, even though the flag reads as optional.
81
+
82
+ **5 — Is the running code the code you think it is?**
83
+
84
+ ```bash
85
+ pikku fabric status # active + in-flight deployment, per stage, with gitSha
86
+ ```
87
+
88
+ Check this *before* deep-diving. A stage still serving an older `gitSha`, or a
89
+ deploy stuck in flight, explains a whole class of "my fix did nothing".
90
+
91
+ ## Known gaps — do not misread these as bugs in your app
92
+
93
+ - **`pikku fabric logs --since` and `--deployment` are accepted and ignored.**
94
+ They are declared as options but the command never reads them, so
95
+ `--since 15m` silently returns the same default window as no flag at all. Do
96
+ not conclude "nothing happened in the last 15 minutes" from it. Narrow by
97
+ `--level`, or by `--function` via `errors`, instead.
98
+ - **`--follow` is a 2-second client-side poll, not a server stream.** It
99
+ dedups against what it already printed, so it behaves like `tail -f`, but new
100
+ entries can appear up to ~2s late and it holds the process open until killed.
101
+
102
+ ## What NOT to do
103
+
104
+ - **Do not SSH anywhere or query the telemetry backend directly.** These
105
+ commands are the supported surface; anything lower-level is Fabric-internal
106
+ and will not exist for your project.
107
+ - **Do not debug by redeploying with added `console.log`s.** Get the traceId,
108
+ read the trace. A deploy cycle per hypothesis is the slow path.
109
+ - **Do not read the truncated `errors` message as the full error.** Always
110
+ confirm against `trace` before changing code.
111
+ - **Do not treat an empty `errors` table as "the app is fine"** — a request that
112
+ returns a wrong 200 logs nothing. Check `metrics` for the outcome mix.
@@ -58,8 +58,8 @@ export const isAuthenticated = pikkuAuth(
58
58
  async (_services, session) => !!session
59
59
  )
60
60
 
61
- export const isAdmin = pikkuAuth(
62
- async (_services, session) => session?.role === 'admin'
61
+ export const isVerified = pikkuAuth(
62
+ async (_services, session) => !!session?.emailVerified
63
63
  )
64
64
  ```
65
65
 
@@ -88,11 +88,11 @@ export const hasBookAccess = pikkuPermission(
88
88
 
89
89
  ```typescript
90
90
  permissions: {
91
- admin: isAdmin, // OR: admins can access
91
+ verified: isVerified, // OR: verified users can access
92
92
  owner: isBookOwner, // OR: owners can access
93
93
  reviewer: [isAuthenticated, hasBookAccess], // AND: both must pass
94
94
  }
95
- // Logic: admin OR owner OR (isAuthenticated AND hasBookAccess)
95
+ // Logic: verified OR owner OR (isAuthenticated AND hasBookAccess)
96
96
  ```
97
97
 
98
98
  Groups are OR'd. Entries within a group array are AND'd.
@@ -107,7 +107,7 @@ export const deleteBook = pikkuFunc({
107
107
  await db.deleteBook(bookId)
108
108
  },
109
109
  permissions: {
110
- admin: isAdmin,
110
+ verified: isVerified,
111
111
  owner: isBookOwner,
112
112
  },
113
113
  })
@@ -146,8 +146,8 @@ export const isAuthenticated = pikkuAuth(
146
146
  async (_services, session) => !!session
147
147
  )
148
148
 
149
- export const isAdmin = pikkuAuth(
150
- async (_services, session) => session?.role === 'admin'
149
+ export const isVerified = pikkuAuth(
150
+ async (_services, session) => !!session?.emailVerified
151
151
  )
152
152
 
153
153
  export const isOrgMember = pikkuPermission(
@@ -162,7 +162,7 @@ export const deleteOrg = pikkuFunc({
162
162
  await db.deleteOrg(orgId)
163
163
  },
164
164
  permissions: {
165
- admin: isAdmin,
165
+ verified: isVerified,
166
166
  owner: [isAuthenticated, isOrgMember],
167
167
  },
168
168
  })
@@ -36,15 +36,44 @@ import {
36
36
  Five exports. `usePikkuRealtime` is only valid when you wired a
37
37
  `PikkuRealtime` class via `createPikku` — see step 3 below.
38
38
 
39
+ ## Resolving the server URL
40
+
41
+ Every client (`createPikku`, realtime, the auth client) resolves its base
42
+ through one shared helper in `src/lib/env.ts`. Write this once:
43
+
44
+ ```ts
45
+ // Endpoints come from env, never hardcoded.
46
+ export function apiUrl(): string {
47
+ // SSR: the client hooks only run in the browser, so a placeholder is fine.
48
+ if (import.meta.env.SSR) {
49
+ return import.meta.env.VITE_API_URL ?? '/__api'
50
+ }
51
+ return import.meta.env.VITE_API_URL ?? `${window.location.origin}/api`
52
+ }
53
+ ```
54
+
55
+ **Never fall back to `http://localhost:3000`.** `import.meta.env.VITE_API_URL`
56
+ is substituted by Vite at *build* time, so any deploy that supplies the URL as
57
+ a *runtime* env var or platform binding leaves it `undefined` in the shipped
58
+ bundle — the fallback is then the only branch that ever runs in the browser. A
59
+ localhost fallback means every request from a deployed app goes to the user's
60
+ own machine. `origin + '/api'` is same-origin, needs no build-time knowledge of
61
+ the domain, and is correct wherever the app is served from.
62
+
63
+ For local dev, set `VITE_API_URL`, or proxy `/api` → your backend in
64
+ `vite.config.ts` under `server.proxy`. One `/api` entry also covers
65
+ `/api/auth/*`; only add more entries for root-level routes outside `/api`.
66
+
39
67
  ## Setup at the app root
40
68
 
41
69
  ```tsx
42
70
  import { createPikku, PikkuProvider } from '@pikku/react'
43
71
  import { PikkuFetch } from './pikku/pikku-fetch.gen'
44
72
  import { PikkuRPC } from './pikku/pikku-rpc.gen'
73
+ import { apiUrl } from './lib/env'
45
74
 
46
75
  const pikku = createPikku(PikkuFetch, PikkuRPC, {
47
- serverUrl: import.meta.env.VITE_API_URL ?? 'http://localhost:3000',
76
+ serverUrl: apiUrl(),
48
77
  })
49
78
 
50
79
  createRoot(document.getElementById('root')!).render(
@@ -62,7 +91,7 @@ the `PikkuRealtime` class as the third argument and the instance gets a
62
91
  import { PikkuRealtime } from './pikku/realtime.gen'
63
92
 
64
93
  const pikku = createPikku(PikkuFetch, PikkuRPC, PikkuRealtime, {
65
- serverUrl: import.meta.env.VITE_API_URL ?? 'http://localhost:3000',
94
+ serverUrl: apiUrl(),
66
95
  })
67
96
  // pikku.fetch / pikku.rpc / pikku.realtime — all share the same fetch
68
97
  // (server URL + auth configured once).
@@ -159,7 +188,7 @@ or set headers on the fetch instance after creation. Common pattern:
159
188
 
160
189
  ```tsx
161
190
  const pikku = createPikku(PikkuFetch, PikkuRPC, {
162
- serverUrl: '...',
191
+ serverUrl: apiUrl(),
163
192
  fetchOptions: {
164
193
  onRequest: (req) => {
165
194
  const token = localStorage.getItem('token')
@@ -59,9 +59,11 @@ import { PikkuProvider, createPikku } from '@pikku/react'
59
59
  import { PikkuFetch } from './pikku/pikku-fetch.gen'
60
60
  import { PikkuRPC } from './pikku/pikku-rpc.gen'
61
61
 
62
+ import { apiUrl } from './lib/env'
63
+
62
64
  const queryClient = new QueryClient()
63
65
  const pikku = createPikku(PikkuFetch, PikkuRPC, {
64
- serverUrl: import.meta.env.VITE_API_URL ?? 'http://localhost:3000',
66
+ serverUrl: apiUrl(),
65
67
  })
66
68
 
67
69
  <QueryClientProvider client={queryClient}>
@@ -75,6 +77,41 @@ The two generated files come from `pikku.config.json`'s
75
77
  `clientFiles.fetchFile` and `clientFiles.rpcWiringsFile`. Hooks live in
76
78
  the file at `clientFiles.reactQueryFile` (typically `api.gen.ts`).
77
79
 
80
+ `apiUrl()` is the shared server-URL helper — see **pikku-react**. Never
81
+ inline `?? 'http://localhost:3000'`: a deploy that supplies the URL as a
82
+ runtime binding leaves `import.meta.env.VITE_API_URL` undefined in the
83
+ bundle, so the fallback is the branch that actually runs.
84
+
85
+ ## TanStack Start (SSR)
86
+
87
+ Under Start the provider mounts in `routes/__root.tsx` rather than
88
+ `main.tsx`, and the same module is evaluated on the server. Three things
89
+ differ:
90
+
91
+ 1. **`apiUrl()` must have an SSR branch.** `window` is undefined during
92
+ render; return the build-time var or a placeholder (the client hooks
93
+ only fire in the browser).
94
+ 2. **Build auth clients lazily.** Better Auth validates its baseURL with
95
+ `new URL(...)` at construction, so a module-scope `createAuthClient`
96
+ crashes SSR on the placeholder. Memoize it behind a getter:
97
+
98
+ ```ts
99
+ let _authClient: ReturnType<typeof createAuthClient> | undefined
100
+ export const authClient = () =>
101
+ (_authClient ??= createAuthClient({ baseURL: `${apiUrl()}/auth` }))
102
+ ```
103
+
104
+ 3. **The auth baseURL needs the `/auth` suffix.** Better Auth only
105
+ appends its default `/api/auth` when the baseURL carries no path.
106
+ `apiUrl()` already ends in `/api`, so a bare `apiUrl()` leaves the
107
+ client calling `/api/get-session` and 404ing.
108
+
109
+ Server functions that need typed RPC access use the generated shim:
110
+
111
+ ```bash
112
+ pikku tanstack-start # emits the makeApi server-function shim
113
+ ```
114
+
78
115
  ## The hooks
79
116
 
80
117
  All hooks are imported from your generated `api.gen.ts`:
@@ -160,7 +160,7 @@ const pikku = createPikku(
160
160
  PikkuFetch,
161
161
  PikkuRPC,
162
162
  PikkuRealtime, // pass the realtime class as the third arg
163
- { serverUrl: import.meta.env.VITE_API_URL ?? 'http://localhost:3000' }
163
+ { serverUrl: apiUrl() } // shared env helper see pikku-react
164
164
  )
165
165
  // pikku.fetch / pikku.rpc / pikku.realtime — all share the same fetch.
166
166
 
@@ -36,7 +36,7 @@ const login = pikkuFunc({
36
36
  auth: false,
37
37
  func: async ({ jwt, db }, { email, password }, { setSession }) => {
38
38
  const user = await db.verifyCredentials(email, password)
39
- setSession({ userId: user.id, role: user.role })
39
+ setSession({ userId: user.id })
40
40
  return { token: jwt.sign({ userId: user.id }) }
41
41
  },
42
42
  })
@@ -80,7 +80,7 @@ addHTTPMiddleware('*', [authAPIKey({ source: 'all' })])
80
80
  import { pikkuAuth, pikkuPermission } from '#pikku'
81
81
 
82
82
  export const isAuthenticated = pikkuAuth(async (_services, session) => !!session)
83
- export const isAdmin = pikkuAuth(async (_services, session) => session?.role === 'admin')
83
+ export const isVerified = pikkuAuth(async (_services, session) => !!session?.emailVerified)
84
84
 
85
85
  // wirings/auth.wiring.ts
86
86
  import { authCookie } from '@pikku/core/middleware'
@@ -95,7 +95,7 @@ export const login = pikkuFunc({
95
95
  auth: false,
96
96
  func: async ({ jwt, db }, { email, password }, { setSession }) => {
97
97
  const user = await db.verifyCredentials(email, password)
98
- setSession({ userId: user.id, role: user.role })
98
+ setSession({ userId: user.id })
99
99
  return { token: jwt.sign({ userId: user.id }) }
100
100
  },
101
101
  })
@@ -2,6 +2,7 @@
2
2
  name: pikku-template-clone
3
3
  description: 'Standard cleanup to run right after a Pikku template is cloned or scaffolded into a new project. TRIGGER when: a Pikku template was just cloned/scaffolded (via `npm create pikku`, `git clone <template>`, or the user says "I cloned the kanban template / starter / template"), or the working tree still looks like an untouched template (template README, placeholder `@project/*` name in package.json). DO NOT TRIGGER when: working in an established project mid-feature, or editing the template repo itself.'
4
4
  allowed-tools: Bash(git status *), Bash(git add *), Bash(git commit *), Bash(git rm *), Bash(git mv *), Bash(git log *)
5
+ installGroups: [core]
5
6
  ---
6
7
 
7
8
  # Pikku Template Post-Clone Cleanup
package/cli.schema.json DELETED
@@ -1 +0,0 @@
1
- {"$schema":"http://json-schema.org/draft-07/schema#","type":"object","additionalProperties":false,"properties":{"configFile":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"wires":{"type":"array","items":{"type":"string"}},"excludeWires":{"type":"array","items":{"type":"string"}},"userSessionType":{"type":"string"},"singletonServicesFactoryType":{"type":"string"},"wireServicesFactoryType":{"type":"string"},"outDir":{"type":"string"},"schemaDirectory":{"type":"string"},"typesDeclarationFile":{"type":"string"},"functionsFile":{"type":"string"},"functionsMetaFile":{"type":"string"},"functionsMetaJsonFile":{"type":"string"},"functionTypesFile":{"type":"string"},"httpWiringsFile":{"type":"string"},"httpWiringMetaFile":{"type":"string"},"httpWiringMetaJsonFile":{"type":"string"},"httpContractsMetaJsonFile":{"type":"string"},"httpContractsMetaFile":{"type":"string"},"httpMapDeclarationFile":{"type":"string"},"httpTypesFile":{"type":"string"},"gatewaysWiringFile":{"type":"string"},"gatewaysWiringMetaFile":{"type":"string"},"gatewaysWiringMetaJsonFile":{"type":"string"},"channelsWiringFile":{"type":"string"},"channelsWiringMetaFile":{"type":"string"},"channelsWiringMetaJsonFile":{"type":"string"},"channelContractsMetaJsonFile":{"type":"string"},"channelContractsMetaFile":{"type":"string"},"channelsMapDeclarationFile":{"type":"string"},"channelsTypesFile":{"type":"string"},"rpcInternalWiringMetaFile":{"type":"string"},"rpcInternalWiringMetaJsonFile":{"type":"string"},"rpcInternalMapDeclarationFile":{"type":"string"},"rpcMapDeclarationFile":{"type":"string"},"rpcRemoteMapDeclarationFile":{"type":"string"},"remoteRpcWorkersFile":{"type":"string"},"graphWiringsFile":{"type":"string"},"webhookWorkersFile":{"type":"string"},"publicRpcFile":{"type":"string"},"publicAgentFile":{"type":"string"},"consoleFunctionsFile":{"type":"string"},"scenariosFunctionsFile":{"type":"string"},"workflowRoutesFile":{"type":"string"},"eventsChannelFile":{"type":"string"},"triggersTypesFile":{"type":"string"},"triggersWiringFile":{"type":"string"},"triggersWiringMetaFile":{"type":"string"},"triggersWiringMetaJsonFile":{"type":"string"},"triggerSourcesMetaFile":{"type":"string"},"triggerSourcesMetaJsonFile":{"type":"string"},"schedulersWiringFile":{"type":"string"},"schedulersWiringMetaFile":{"type":"string"},"schedulersWiringMetaJsonFile":{"type":"string"},"schedulersTypesFile":{"type":"string"},"queueWorkersWiringFile":{"type":"string"},"queueWorkersWiringMetaFile":{"type":"string"},"queueWorkersWiringMetaJsonFile":{"type":"string"},"queueMapDeclarationFile":{"type":"string"},"queueTypesFile":{"type":"string"},"workflowsWiringFile":{"type":"string"},"workflowsWiringMetaFile":{"type":"string"},"workflowsWorkersFile":{"type":"string"},"workflowMapDeclarationFile":{"type":"string"},"workflowTypesFile":{"type":"string"},"workflowMetaDir":{"type":"string"},"scenarioActorsFile":{"type":"string"},"mcpWiringsFile":{"type":"string"},"mcpWiringsMetaFile":{"type":"string"},"mcpWiringsMetaJsonFile":{"type":"string"},"mcpTypesFile":{"type":"string"},"mcpJsonFile":{"type":"string"},"agentWiringsFile":{"type":"string"},"agentWiringMetaFile":{"type":"string"},"agentWiringMetaJsonFile":{"type":"string"},"agentTypesFile":{"type":"string"},"agentMapDeclarationFile":{"type":"string"},"cliWiringsFile":{"type":"string"},"cliWiringMetaFile":{"type":"string"},"cliWiringMetaJsonFile":{"type":"string"},"cliContractsMetaJsonFile":{"type":"string"},"cliContractsMetaFile":{"type":"string"},"cliBootstrapFile":{"type":"string"},"cliTypesFile":{"type":"string"},"servicesFile":{"type":"string"},"middlewareFile":{"type":"string"},"middlewareGroupsMetaJsonFile":{"type":"string"},"permissionsFile":{"type":"string"},"permissionsGroupsMetaJsonFile":{"type":"string"},"bootstrapFile":{"type":"string"},"packageFile":{"type":"string"},"addonTypesFile":{"type":"string"},"nodeTypesFile":{"type":"string"},"secretTypesFile":{"type":"string"},"secretsFile":{"type":"string"},"secretsMetaJsonFile":{"type":"string"},"credentialsFile":{"type":"string"},"credentialsMetaJsonFile":{"type":"string"},"scopeTypesFile":{"type":"string"},"scopesFile":{"type":"string"},"scopesMetaJsonFile":{"type":"string"},"variableTypesFile":{"type":"string"},"variablesFile":{"type":"string"},"variablesMetaJsonFile":{"type":"string"},"$schema":{"type":"string"},"extends":{"type":"string"},"rootDir":{"type":"string"},"runtimeDir":{"type":"string","description":"Runtime artifacts directory (dev.db, content, tmp). Resolved relative to rootDir. Defaults to <rootDir>/.pikku-runtime."},"srcDirectories":{"type":"array","items":{"type":"string"}},"ignoreFiles":{"type":"array","items":{"type":"string"}},"packageMappings":{"type":"object","additionalProperties":{"type":"string"}},"addon":{"anyOf":[{"type":"boolean"},{"type":"object","properties":{"categories":{"type":"array","items":{"type":"string"}},"icon":{"type":"string"},"displayName":{"type":"string"},"description":{"type":"string"},"serverlessIncompatible":{"type":"array","items":{"type":"string"}},"openapi":{"type":"object","properties":{"version":{"type":"string"},"hash":{"type":"string"}},"required":["version","hash"],"additionalProperties":false}},"additionalProperties":false}]},"addonName":{"type":"string"},"configDir":{"type":"string"},"tsconfig":{"type":"string"},"clientFiles":{"type":"object","properties":{"fetchFile":{"type":"string"},"websocketFile":{"type":"string"},"rpcWiringsFile":{"type":"string"},"reactQueryFile":{"type":"string"},"realtimeFile":{"type":"string"},"realtimeEventHubTopicsImport":{"type":"string","description":"Optional import for the EventHubTopics type so the realtime client is fully typed. Format: `<path>#<TypeName>` resolved relative to `realtimeFile`. Example: `../types/eventhub-topics.js#EventHubTopics`. If unset, the generated client treats topics as `Record<string, unknown>`."},"queueWiringsFile":{"type":"string"},"mcpJsonFile":{"type":"string"},"nextBackendFile":{"type":"string"},"nextHTTPFile":{"type":"string"},"nextBackendTransport":{"type":"string","enum":["local","worker-rpc","http"],"description":"Transport used by the generated nextBackendFile wrapper.\n- `'local'` (default): function code is loaded in-process via bootstrap + createSingletonServices. Required for Node/dev runs.\n- `'worker-rpc'`: SSR dispatches every call through an injected `Fetcher` ({ fetch(req): Promise<Response> }). Function code is NOT bundled into the SSR worker. Pair with `nextBackendFetcherImport` to point at your resolver module.\n- `'http'`: SSR dispatches every call through the generated `PikkuFetch` client. Use this when your Next app should call a separately running local/server API instead of importing function code in-process."},"nextBackendFetcherImport":{"type":"string","description":"Module that exports a `fetcher: Fetcher` (or default export) used by the worker-RPC variant of the next backend wrapper. Resolved relative to `nextBackendFile`. Required when `nextBackendTransport === 'worker-rpc'`."},"startServerFnsFile":{"type":"string","description":"Emit a TanStack Start server-function shim into this file. The shim exports `makeApi(): PikkuRPC` — a typed caller over the generated RPC map for use in Start loaders, actions and components. It reads the API base URL from `import.meta.env.VITE_API_URL` (throws if unset). Requires `rpcWiringsFile` (where the `PikkuRPC` class is generated)."}},"additionalProperties":false},"emailTemplatesDir":{"type":"string","description":"Directory containing email templates, locales, partials, and theme.json."},"authFile":{"type":"string","description":"Path to write the generated Better Auth wiring file (auth.gen.ts). Must be within srcDirectories so wireSecret calls are picked up by the inspector. Example: \"src/auth.gen.ts\""},"authTypesFile":{"type":"string","description":"Path to write the generated typed `pikkuBetterAuth` re-export (auth.types.ts). Defaults to `{outDir}/auth/auth.types.ts`. Re-exported from `#pikku` so user code can `import { pikkuBetterAuth } from '#pikku'` with project-typed services."},"authMetaJsonFile":{"type":"string","description":"Path to write the generated Better Auth metadata (auth-meta.gen.json) — the enabled social providers and plugins the console SSO page reads via getAuthProviders. Defaults to `{outDir}/auth/pikku-auth-meta.gen.json`."},"openAPI":{"type":"object","properties":{"outputFile":{"type":"string"},"additionalInfo":{"$ref":"#/definitions/OpenAPISpecInfo"}},"required":["outputFile","additionalInfo"],"additionalProperties":false},"schema":{"type":"object","properties":{"additionalProperties":{"type":"boolean"},"supportsImportAttributes":{"type":"boolean"}},"additionalProperties":false},"db":{"type":"object","properties":{"engine":{"type":"string","enum":["sqlite","postgres"]},"pgVersion":{"type":"number"}},"additionalProperties":false},"cli":{"type":"object","properties":{"entrypoints":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"object","properties":{"type":{"type":"string","const":"local"},"path":{"type":"string"}},"required":["type","path"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"channel"},"name":{"type":"string"},"route":{"type":"string"},"wirePath":{"type":"string"},"path":{"type":"string"}},"required":["type","wirePath"],"additionalProperties":false},{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","properties":{"type":{"type":"string","const":"local"},"path":{"type":"string"}},"required":["type","path"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","const":"channel"},"name":{"type":"string"},"route":{"type":"string"},"wirePath":{"type":"string"},"path":{"type":"string"}},"required":["type","wirePath"],"additionalProperties":false}]}}]}}},"additionalProperties":false},"workflows":{"type":"object","properties":{"orchestratorQueue":{"type":"string"},"workerQueue":{"type":"string"}},"additionalProperties":false},"scenarios":{"type":"object","properties":{"actors":{"type":"object","additionalProperties":{"type":"object","properties":{"email":{"type":"string"},"name":{"type":"string"},"jobTitle":{"type":"string"},"personality":{"type":"string"}},"required":["email"],"additionalProperties":false},"description":"Global scenario actor registry — any scenario can impersonate any actor"},"environments":{"type":"object","additionalProperties":{"type":"object","properties":{"apiUrl":{"type":"string"},"signInPath":{"type":"string","description":"Actor sign-in path under apiUrl. Default: /auth/sign-in/actor"},"rpcPath":{"type":"string","description":"Exposed-RPC prefix under apiUrl. Default: /rpc"}},"required":["apiUrl"],"additionalProperties":false},"description":"Environments `pikku scenario run <environment>` can target; the actor secret comes from SCENARIO_ACTOR_SECRET, never config"}},"additionalProperties":false},"scaffold":{"type":"object","properties":{"addonDir":{"type":"string"},"functionDir":{"type":"string"},"wiringDir":{"type":"string"},"middlewareDir":{"type":"string"},"permissionDir":{"type":"string"},"pikkuDir":{"type":"string"},"graph":{"type":"boolean","description":"Wire the pikku addon-graph package so pikkuWorkflowGraph can reference its native transforms like graph:editFields."},"rpc":{"$ref":"#/definitions/PikkuScaffoldFeature"},"console":{"$ref":"#/definitions/PikkuScaffoldFeature"},"scenarios":{"$ref":"#/definitions/PikkuScaffoldFeature"},"agent":{"$ref":"#/definitions/PikkuScaffoldFeature"},"workflow":{"$ref":"#/definitions/PikkuScaffoldFeature"},"events":{"$ref":"#/definitions/PikkuScaffoldFeature"},"remoteRpc":{"$ref":"#/definitions/PikkuScaffoldFeature"},"webhook":{"type":"boolean","description":"The outgoing webhook delivery worker exposes no endpoint of its own, so it has no auth dimension — it is on or off."}},"additionalProperties":false},"addons":{"type":"object","properties":{"addonDir":{"type":"string"}},"additionalProperties":false,"description":"Community-registry addons installed via `pikku fabric addon add`. The source is copied into the project shadcn-style; each lands in `<addonDir>/<name>/` and the dir is registered as a yarn workspace so `wireAddon({ package })` resolves it by name. `addonDir` defaults to `addons` (top-level, outside the app's TS scan). Install provenance is tracked in pikku-addons.json."},"tests":{"type":"object","properties":{"outputDir":{"type":"string"}},"additionalProperties":false},"forceRequiredServices":{"type":"array","items":{"type":"string"}},"schemasFromTypes":{"type":"array","items":{"type":"string"}},"stateOutput":{"type":"string"},"stateInput":{"type":"string"},"verboseMeta":{"type":"boolean"},"security":{"type":"boolean","description":"Run the data-classification security lint (scans function return types for Private/Pii/Secret leaks). Off by default — it forces expensive return-type inference on every function and is not part of codegen. Enable here to always run it, or per-invocation via `pikku all --security`. Pair with `failOnError` to gate a build/CI on leaks."},"tsc":{"type":"boolean","description":"After codegen, run a real `tsc --noEmit` over the project's tsconfig and fail on type errors. `tsc` prints full diagnostics with code frames; `tscSummary` prints a compact one-line-per-error render (no code frames, capped) that's cheap for AI agents / CI logs. Off by default; enable per invocation via `pikku all --tsc` / `--tsc-summary`."},"tscSummary":{"type":"boolean"},"diff":{"type":"boolean","description":"After a successful codegen run, emit a structural diff of the generated `.pikku` meta (functions/wirings/workflows/emails added/removed/changed vs the state before this run) as a `PIKKU_DIFF <json>` line on stdout. Only emitted on exit 0. Off by default; enable per invocation via `pikku all --diff`. Consumed by the sandbox \"what changed\" build card."},"lint":{"type":"object","properties":{"servicesNotDestructured":{"type":"string","enum":["off","warn","error"]},"wiresNotDestructured":{"type":"string","enum":["off","warn","error"]},"functionDynamicImport":{"type":"string","enum":["off","warn","error"]}},"additionalProperties":false},"addonMetaJsonFile":{"type":"string"},"globalHTTPPrefix":{"type":"string"},"binary":{"type":"object","properties":{"entrypoint":{"type":"string"},"output":{"type":"string"},"targets":{"type":"array","items":{"type":"string"}}},"required":["entrypoint","output"],"additionalProperties":false},"deploy":{"type":"object","properties":{"providers":{"type":"object","additionalProperties":{"type":"string"}},"defaultProvider":{"type":"string"},"serverlessIncompatible":{"type":"array","items":{"type":"string"}},"defaultTarget":{"type":"string","enum":["serverless","server"],"description":"Default deploy target for functions that don't declare an explicit `deploy` flag and don't use a serverless-incompatible service. Defaults to 'serverless'."}},"required":["providers"],"additionalProperties":false},"namedFilters":{"type":"object","additionalProperties":{"$ref":"#/definitions/InspectorFilters"},"description":"Named filter presets keyed by name, used via CLI --filter <name>."},"filters":{"$ref":"#/definitions/InspectorFilters"}},"required":["addonTypesFile","agentMapDeclarationFile","agentTypesFile","agentWiringMetaFile","agentWiringMetaJsonFile","agentWiringsFile","bootstrapFile","channelContractsMetaFile","channelContractsMetaJsonFile","channelsMapDeclarationFile","channelsTypesFile","channelsWiringFile","channelsWiringMetaFile","channelsWiringMetaJsonFile","cliBootstrapFile","cliContractsMetaFile","cliContractsMetaJsonFile","cliTypesFile","cliWiringMetaFile","cliWiringMetaJsonFile","cliWiringsFile","configDir","consoleFunctionsFile","credentialsFile","credentialsMetaJsonFile","eventsChannelFile","filters","functionTypesFile","functionsFile","functionsMetaFile","functionsMetaJsonFile","gatewaysWiringFile","gatewaysWiringMetaFile","gatewaysWiringMetaJsonFile","httpContractsMetaFile","httpContractsMetaJsonFile","httpMapDeclarationFile","httpTypesFile","httpWiringMetaFile","httpWiringMetaJsonFile","httpWiringsFile","mcpJsonFile","mcpTypesFile","mcpWiringsFile","mcpWiringsMetaFile","mcpWiringsMetaJsonFile","middlewareFile","middlewareGroupsMetaJsonFile","nodeTypesFile","outDir","packageFile","packageMappings","permissionsFile","permissionsGroupsMetaJsonFile","publicAgentFile","publicRpcFile","queueMapDeclarationFile","queueTypesFile","queueWorkersWiringFile","queueWorkersWiringMetaFile","queueWorkersWiringMetaJsonFile","rootDir","rpcInternalMapDeclarationFile","rpcInternalWiringMetaFile","rpcInternalWiringMetaJsonFile","rpcMapDeclarationFile","rpcRemoteMapDeclarationFile","scenarioActorsFile","scenariosFunctionsFile","schedulersTypesFile","schedulersWiringFile","schedulersWiringMetaFile","schedulersWiringMetaJsonFile","schemaDirectory","scopeTypesFile","scopesFile","scopesMetaJsonFile","secretTypesFile","secretsFile","secretsMetaJsonFile","servicesFile","srcDirectories","triggerSourcesMetaFile","triggerSourcesMetaJsonFile","triggersTypesFile","triggersWiringFile","triggersWiringMetaFile","triggersWiringMetaJsonFile","tsconfig","typesDeclarationFile","variableTypesFile","variablesFile","variablesMetaJsonFile","workflowMapDeclarationFile","workflowMetaDir","workflowRoutesFile","workflowTypesFile","workflowsWiringFile","workflowsWiringMetaFile","workflowsWorkersFile"],"definitions":{"OpenAPISpecInfo":{"type":"object","properties":{"info":{"type":"object","properties":{"title":{"type":"string"},"version":{"type":"string"},"description":{"type":"string"},"termsOfService":{"type":"string"},"contact":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"email":{"type":"string"}},"additionalProperties":false},"license":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"}},"required":["name"],"additionalProperties":false}},"required":["title","version","description"],"additionalProperties":false},"servers":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"description":{"type":"string"}},"required":["url"],"additionalProperties":false}},"tags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string"}},"required":["name"],"additionalProperties":false}},"externalDocs":{"type":"object","properties":{"description":{"type":"string"},"url":{"type":"string"}},"required":["url"],"additionalProperties":false},"securitySchemes":{"type":"object"},"security":{"type":"array","items":{"type":"object","additionalProperties":{"type":"array","items":{}}}}},"required":["info","servers"],"additionalProperties":false},"PikkuScaffoldFeature":{"type":["string","boolean"],"enum":["auth","no-auth",false]},"InspectorFilters":{"type":"object","properties":{"names":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}},"wires":{"type":"array","items":{"type":"string"}},"directories":{"type":"array","items":{"type":"string"}},"httpRoutes":{"type":"array","items":{"type":"string"}},"httpMethods":{"type":"array","items":{"type":"string"}},"excludeNames":{"type":"array","items":{"type":"string"}},"excludeTags":{"type":"array","items":{"type":"string"}},"excludeWires":{"type":"array","items":{"type":"string"}},"excludeDirectories":{"type":"array","items":{"type":"string"}},"excludeHttpRoutes":{"type":"array","items":{"type":"string"}},"excludeHttpMethods":{"type":"array","items":{"type":"string"}},"target":{"type":"array","items":{"type":"string","enum":["serverless","server"]}},"excludeTarget":{"type":"array","items":{"type":"string","enum":["serverless","server"]}},"serverlessIncompatible":{"type":"array","items":{"type":"string"}},"defaultTarget":{"type":"string","enum":["serverless","server"]}},"additionalProperties":false}}}