@pikku/cli 0.12.93 → 0.12.96

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 (180) hide show
  1. package/console-app/assets/{index-CmAplHjZ.js → index-CeQodYfg.js} +149 -149
  2. package/console-app/assets/{index-BYj7ZbUU.css → index-CyYHTGWZ.css} +1 -1
  3. package/console-app/index.html +2 -2
  4. package/dist/.pikku/agent/pikku-agent-types.gen.d.ts +1 -1
  5. package/dist/.pikku/channel/pikku-channel-types.gen.d.ts +1 -1
  6. package/dist/.pikku/channel/pikku-channel-types.gen.js +1 -1
  7. package/dist/.pikku/cli/pikku-cli-channel.d.ts +13 -15
  8. package/dist/.pikku/cli/pikku-cli-channel.js +62 -3
  9. package/dist/.pikku/cli/pikku-cli-client.gen.d.ts +14 -4
  10. package/dist/.pikku/cli/pikku-cli-client.gen.js +20 -10
  11. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.d.ts +1 -1
  12. package/dist/.pikku/cli/pikku-cli-contracts-meta.gen.js +1 -1
  13. package/dist/.pikku/cli/pikku-cli-types.gen.d.ts +1 -1
  14. package/dist/.pikku/cli/pikku-cli-types.gen.js +1 -1
  15. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.js +1 -1
  16. package/dist/.pikku/cli/pikku-cli-wirings-meta.gen.json +129 -2
  17. package/dist/.pikku/cli/pikku-cli-wirings.gen.d.ts +1 -1
  18. package/dist/.pikku/cli/pikku-cli-wirings.gen.js +1 -1
  19. package/dist/.pikku/cli/pikku-cli.gen.d.ts +1 -1
  20. package/dist/.pikku/cli/pikku-cli.gen.js +1 -1
  21. package/dist/.pikku/console/pikku-node-types.gen.d.ts +1 -1
  22. package/dist/.pikku/function/pikku-function-types.gen.d.ts +55 -20
  23. package/dist/.pikku/function/pikku-function-types.gen.js +27 -1
  24. package/dist/.pikku/function/pikku-functions-meta.gen.js +1 -1
  25. package/dist/.pikku/function/pikku-functions-meta.gen.json +138 -13
  26. package/dist/.pikku/function/pikku-functions.gen.js +11 -1
  27. package/dist/.pikku/http/pikku-http-types.gen.d.ts +1 -1
  28. package/dist/.pikku/http/pikku-http-types.gen.js +1 -1
  29. package/dist/.pikku/mcp/pikku-mcp-types.gen.d.ts +1 -1
  30. package/dist/.pikku/mcp/pikku-mcp-types.gen.js +1 -1
  31. package/dist/.pikku/pikku-bootstrap-scenarios.gen.d.ts +1 -1
  32. package/dist/.pikku/pikku-bootstrap-scenarios.gen.js +1 -1
  33. package/dist/.pikku/pikku-bootstrap.gen.d.ts +1 -1
  34. package/dist/.pikku/pikku-bootstrap.gen.js +1 -1
  35. package/dist/.pikku/pikku-meta-service.gen.d.ts +1 -1
  36. package/dist/.pikku/pikku-meta-service.gen.js +1 -1
  37. package/dist/.pikku/pikku-services.gen.d.ts +1 -1
  38. package/dist/.pikku/pikku-types.gen.d.ts +1 -1
  39. package/dist/.pikku/pikku-types.gen.js +1 -1
  40. package/dist/.pikku/queue/pikku-queue-types.gen.d.ts +1 -1
  41. package/dist/.pikku/queue/pikku-queue-types.gen.js +1 -1
  42. package/dist/.pikku/queue/pikku-queue-workers-wirings-meta.gen.js +1 -1
  43. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.d.ts +1 -1
  44. package/dist/.pikku/queue/pikku-queue-workers-wirings.gen.js +1 -1
  45. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.js +1 -1
  46. package/dist/.pikku/rpc/pikku-rpc-wirings-meta.internal.gen.json +7 -0
  47. package/dist/.pikku/scenarios/pikku-scenario-functions-meta.gen.js +1 -1
  48. package/dist/.pikku/scenarios/pikku-scenario-functions.gen.d.ts +1 -1
  49. package/dist/.pikku/scenarios/pikku-scenario-wirings-meta.gen.js +1 -1
  50. package/dist/.pikku/scenarios/pikku-scenario-wirings.gen.d.ts +1 -1
  51. package/dist/.pikku/scenarios/schemas/register.gen.d.ts +1 -1
  52. package/dist/.pikku/scenarios/schemas/register.gen.js +1 -1
  53. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.d.ts +1 -1
  54. package/dist/.pikku/scheduler/pikku-scheduler-types.gen.js +1 -1
  55. package/dist/.pikku/schemas/register.gen.js +13 -3
  56. package/dist/.pikku/schemas/schemas/PersonaRunInput.schema.json +1 -0
  57. package/dist/.pikku/schemas/schemas/PersonaSyncInput.schema.json +1 -0
  58. package/dist/.pikku/schemas/schemas/PikkuCLIConfig.schema.json +1 -1
  59. package/dist/.pikku/schemas/schemas/PikkuPersonasInput.schema.json +1 -0
  60. package/dist/.pikku/schemas/schemas/PikkuRolesInput.schema.json +1 -0
  61. package/dist/.pikku/schemas/schemas/RolesAuditInput.schema.json +1 -0
  62. package/dist/.pikku/schemas/schemas/RolesPruneInput.schema.json +1 -0
  63. package/dist/.pikku/scopes/pikku-personas-meta.gen.json +1 -0
  64. package/dist/.pikku/scopes/pikku-personas.gen.d.ts +36 -0
  65. package/dist/.pikku/scopes/pikku-personas.gen.js +17 -0
  66. package/dist/.pikku/scopes/pikku-roles-meta.gen.json +1 -0
  67. package/dist/.pikku/scopes/pikku-roles.gen.d.ts +30 -0
  68. package/dist/.pikku/scopes/pikku-roles.gen.js +18 -0
  69. package/dist/.pikku/scopes/pikku-scope-types.gen.d.ts +4 -2
  70. package/dist/.pikku/scopes/pikku-scope-types.gen.js +3 -2
  71. package/dist/.pikku/scopes/pikku-scopes.gen.d.ts +1 -1
  72. package/dist/.pikku/secrets/pikku-secret-types.gen.d.ts +2 -2
  73. package/dist/.pikku/secrets/pikku-secret-types.gen.js +2 -2
  74. package/dist/.pikku/secrets/pikku-secrets.gen.d.ts +1 -1
  75. package/dist/.pikku/secrets/pikku-secrets.gen.js +1 -1
  76. package/dist/.pikku/trigger/pikku-trigger-types.gen.d.ts +1 -1
  77. package/dist/.pikku/trigger/pikku-trigger-types.gen.js +1 -1
  78. package/dist/.pikku/variables/pikku-variable-types.gen.d.ts +2 -2
  79. package/dist/.pikku/variables/pikku-variable-types.gen.js +2 -2
  80. package/dist/.pikku/variables/pikku-variables.gen.d.ts +1 -1
  81. package/dist/.pikku/variables/pikku-variables.gen.js +1 -1
  82. package/dist/.pikku/workflow/meta/allWorkflow.gen.json +27 -3
  83. package/dist/.pikku/workflow/pikku-personas.gen.d.ts +15 -0
  84. package/dist/.pikku/workflow/pikku-personas.gen.js +17 -0
  85. package/dist/.pikku/workflow/pikku-workflow-types.gen.d.ts +96 -19
  86. package/dist/.pikku/workflow/pikku-workflow-types.gen.js +22 -2
  87. package/dist/.pikku/workflow/pikku-workflow-wirings-meta.gen.js +1 -1
  88. package/dist/.pikku/workflow/pikku-workflow-wirings.gen.js +1 -1
  89. package/dist/bin/pikku-bin.mjs +2 -2
  90. package/dist/bin/pikku.js +0 -0
  91. package/dist/src/cli.wiring.js +101 -2
  92. package/dist/src/deploy/analyzer/analyzer.js +14 -0
  93. package/dist/src/deploy/analyzer/manifest.d.ts +11 -0
  94. package/dist/src/fabric/functions/validate.function.js +4 -4
  95. package/dist/src/functions/commands/bootstrap.js +3 -0
  96. package/dist/src/functions/commands/dev-ai-runner.d.ts +16 -4
  97. package/dist/src/functions/commands/dev-ai-runner.js +63 -29
  98. package/dist/src/functions/commands/dev.js +9 -4
  99. package/dist/src/functions/commands/enable.js +15 -19
  100. package/dist/src/functions/commands/{scenario-environment.d.ts → environment.d.ts} +9 -6
  101. package/dist/src/functions/commands/{scenario-environment.js → environment.js} +5 -4
  102. package/dist/src/functions/commands/new-addon.js +12 -12
  103. package/dist/src/functions/commands/persona-sync.d.ts +33 -0
  104. package/dist/src/functions/commands/persona-sync.js +151 -0
  105. package/dist/src/functions/commands/persona.d.ts +58 -0
  106. package/dist/src/functions/commands/persona.js +217 -0
  107. package/dist/src/functions/commands/roles-audit.d.ts +1 -0
  108. package/dist/src/functions/commands/roles-audit.js +37 -0
  109. package/dist/src/functions/commands/roles-prune.d.ts +16 -0
  110. package/dist/src/functions/commands/roles-prune.js +52 -0
  111. package/dist/src/functions/commands/roles-shared.d.ts +40 -0
  112. package/dist/src/functions/commands/roles-shared.js +77 -0
  113. package/dist/src/functions/commands/scenario-browser.d.ts +3 -3
  114. package/dist/src/functions/commands/scenario-browser.js +1 -1
  115. package/dist/src/functions/commands/scenario-ladder.d.ts +44 -2
  116. package/dist/src/functions/commands/scenario-ladder.js +51 -2
  117. package/dist/src/functions/commands/scenario.d.ts +7 -0
  118. package/dist/src/functions/commands/scenario.js +79 -17
  119. package/dist/src/functions/commands/scopes-shared.d.ts +8 -0
  120. package/dist/src/functions/commands/scopes-shared.js +1 -1
  121. package/dist/src/functions/commands/serve.js +7 -3
  122. package/dist/src/functions/commands/virtual-user-formatter.d.ts +30 -0
  123. package/dist/src/functions/commands/virtual-user-formatter.js +65 -0
  124. package/dist/src/functions/db/local-db.js +38 -1
  125. package/dist/src/functions/validate/workspace-validate.js +1 -1
  126. package/dist/src/functions/wirings/ai-agent/pikku-command-public-agent.js +2 -1
  127. package/dist/src/functions/wirings/ai-agent/serialize-public-agent.js +1 -0
  128. package/dist/src/functions/wirings/auth/serialize-auth-gen.d.ts +2 -2
  129. package/dist/src/functions/wirings/auth/serialize-auth-gen.js +8 -8
  130. package/dist/src/functions/wirings/cli/serialize-channel-cli-client.d.ts +7 -3
  131. package/dist/src/functions/wirings/cli/serialize-channel-cli-client.js +32 -18
  132. package/dist/src/functions/wirings/cli/serialize-channel-cli.js +63 -6
  133. package/dist/src/functions/wirings/console/serialize-console-functions.js +4 -7
  134. package/dist/src/functions/wirings/functions/serialize-function-types.js +88 -28
  135. package/dist/src/functions/wirings/middleware/serialize-middleware-imports.js +25 -9
  136. package/dist/src/functions/wirings/package/serialize-package-types.js +5 -3
  137. package/dist/src/functions/wirings/personas/pikku-command-personas.d.ts +7 -0
  138. package/dist/src/functions/wirings/personas/pikku-command-personas.js +43 -0
  139. package/dist/src/functions/wirings/personas/serialize-personas-types.d.ts +18 -0
  140. package/dist/src/functions/wirings/personas/serialize-personas-types.js +76 -0
  141. package/dist/src/functions/wirings/realtime/pikku-command-events-scaffold.js +2 -1
  142. package/dist/src/functions/wirings/roles/pikku-command-roles.d.ts +7 -0
  143. package/dist/src/functions/wirings/roles/pikku-command-roles.js +33 -0
  144. package/dist/src/functions/wirings/roles/serialize-roles-types.d.ts +14 -0
  145. package/dist/src/functions/wirings/roles/serialize-roles-types.js +55 -0
  146. package/dist/src/functions/wirings/rpc/pikku-command-public-rpc.js +2 -1
  147. package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.d.ts +3 -3
  148. package/dist/src/functions/wirings/scenarios/register-scenario-instrumentation.js +3 -3
  149. package/dist/src/functions/wirings/scopes/serialize-scopes-types.d.ts +1 -1
  150. package/dist/src/functions/wirings/scopes/serialize-scopes-types.js +1 -1
  151. package/dist/src/functions/wirings/user-admin/pikku-command-user-admin-functions.js +2 -1
  152. package/dist/src/functions/wirings/user-admin/serialize-user-admin-functions.js +2 -2
  153. package/dist/src/functions/wirings/workflow/pikku-command-workflow-routes.js +2 -1
  154. package/dist/src/functions/wirings/workflow/pikku-command-workflow.js +13 -13
  155. package/dist/src/functions/wirings/workflow/serialize-personas.d.ts +10 -0
  156. package/dist/src/functions/wirings/workflow/serialize-personas.js +46 -0
  157. package/dist/src/functions/wirings/workflow/serialize-scenario-step-map.js +11 -2
  158. package/dist/src/functions/wirings/workflow/serialize-workflow-types.js +165 -29
  159. package/dist/src/functions/workflows/all.workflow.js +7 -1
  160. package/dist/src/server/content-signing-jwt.d.ts +13 -0
  161. package/dist/src/server/content-signing-jwt.js +51 -0
  162. package/dist/src/server/dev-server-runner.interface.d.ts +10 -2
  163. package/dist/src/server/node-server-runner.d.ts +2 -2
  164. package/dist/src/server/node-server-runner.js +2 -1
  165. package/dist/src/services.d.ts +3 -1
  166. package/dist/src/services.js +2 -1
  167. package/dist/src/utils/pikku-cli-config.js +45 -2
  168. package/dist/src/utils/resolve-personas.d.ts +32 -0
  169. package/dist/src/utils/resolve-personas.js +46 -0
  170. package/dist/src/utils/resolve-scaffold-feature.d.ts +19 -0
  171. package/dist/src/utils/resolve-scaffold-feature.js +49 -0
  172. package/dist/tsconfig.tsbuildinfo +1 -1
  173. package/package.json +17 -14
  174. package/dist/.pikku/schemas/schemas/ScenarioRunInput.schema.json +0 -1
  175. package/dist/.pikku/workflow/pikku-scenario-actors.gen.d.ts +0 -19
  176. package/dist/.pikku/workflow/pikku-scenario-actors.gen.js +0 -17
  177. package/dist/src/functions/wirings/workflow/serialize-scenario-actors.d.ts +0 -2
  178. package/dist/src/functions/wirings/workflow/serialize-scenario-actors.js +0 -40
  179. package/dist/src/utils/resolve-scenario-actors.d.ts +0 -23
  180. package/dist/src/utils/resolve-scenario-actors.js +0 -74
@@ -60,7 +60,7 @@ export function serializeChannelCLI(programName, programMeta, channelFile, funct
60
60
  import { wireChannel } from '${channelTypesPath}'
61
61
  import { pikkuMiddleware${hasAddonFuncs ? ', ref' : ''}, pikkuSessionlessFunc } from '${functionTypesPath}'
62
62
  import { generateCommandHelp } from '@pikku/core/cli'
63
- import { handleRawCLI } from '@pikku/core/cli/channel'
63
+ import { handleRawCLI, type RawCLIFrame } from '@pikku/core/cli/channel'
64
64
  import { pikkuState } from '@pikku/core/internal'
65
65
  ${imports}
66
66
 
@@ -97,22 +97,79 @@ export const cliHelp = pikkuSessionlessFunc<{ args?: string[] }, { help: string
97
97
  },
98
98
  })
99
99
 
100
- export const cliRaw = pikkuSessionlessFunc<{ args: string[] }, { help?: string; result?: unknown; error?: string }>({
100
+ /**
101
+ * Raw entry point: the client forwards argv untouched and this side owns
102
+ * parsing, so a client binary never carries the command tree and its version
103
+ * is free to drift from the server's.
104
+ *
105
+ * Progressive output is streamed on the same channel rather than returned,
106
+ * and the terminating control frame carries the exit code so the client
107
+ * process can exit non-zero.
108
+ */
109
+ export const cliRaw = pikkuSessionlessFunc<{ args: string[] }, RawCLIFrame>({
101
110
  auth: false,
102
- func: async (services, data: { args: string[] }) => {
103
- return handleRawCLI({
111
+ func: async (services, data: { args: string[] }, { channel, session }) => {
112
+ const { help, result, error, exitCode, commandId } = await handleRawCLI({
104
113
  programName: '${programName}',
105
114
  args: data.args,
106
115
  singletonServices: services as any,
116
+ createWireServices: pikkuState(null, 'package', 'factories')?.createWireServices,
117
+ // The connection authenticated during its upgrade — commands run as it.
118
+ session,
119
+ // The socket the command arrived on, so \`channel.remote(...)\` inside a
120
+ // command reaches the client that invoked it.
121
+ transport: channel,
122
+ onOutput: (output, commandId) =>
123
+ channel?.send({ action: 'cli-output', commandId, data: output }),
107
124
  })
125
+
126
+ // A failed parse carries both: the error says what was wrong, the help
127
+ // says what was available. The error goes last so it is the line still on
128
+ // screen after the help text has scrolled past.
129
+ if (help !== undefined) {
130
+ await channel?.send({ action: 'cli-help', help })
131
+ if (error !== undefined) {
132
+ await channel?.send({ action: 'cli-error', error })
133
+ }
134
+ } else if (error !== undefined) {
135
+ await channel?.send({ action: 'cli-error', error })
136
+ } else if (result !== undefined) {
137
+ await channel?.send({ action: 'cli-result', commandId, result })
138
+ }
139
+
140
+ // Returned rather than sent so the runtime tags it with the routing key,
141
+ // and so the terminal frame cannot be emitted before the ones above it.
142
+ return { action: 'cli-control', event: 'complete', exitCode }
108
143
  },
109
144
  })
110
145
 
146
+ ${programMeta.auth === true
147
+ ? `/**
148
+ * Refuses a connection that arrives without a session.
149
+ *
150
+ * A CLI authenticates once, when it connects — there is no later message that
151
+ * would establish a session, so a connection that starts anonymous can never
152
+ * run anything. Saying so immediately and hanging up gives the caller a
153
+ * non-zero exit instead of a socket that silently refuses every command.
154
+ */
155
+ export const cliRequireSession = pikkuSessionlessFunc<void, RawCLIFrame | void>({
156
+ auth: false,
157
+ func: async (_services, _data, { channel, session }) => {
158
+ if (session) {
159
+ return
160
+ }
161
+ await channel?.send({ action: 'cli-error', error: 'Authentication required' })
162
+ await channel?.send({ action: 'cli-control', event: 'complete', exitCode: 1 })
163
+ await channel?.close()
164
+ },
165
+ })
166
+ `
167
+ : ''}
111
168
  wireChannel({
112
169
  name: '${finalChannelName}',
113
170
  route: '${finalChannelRoute}',
114
- auth: false,
115
- onMessageWiring: {
171
+ auth: ${programMeta.auth === true},
172
+ ${programMeta.auth === true ? ' onConnect: cliRequireSession,\n' : ''} onMessageWiring: {
116
173
  command: {
117
174
  '__help': {
118
175
  func: cliHelp,
@@ -40,6 +40,7 @@ import {
40
40
  } from './console.schemas.gen.js'
41
41
 
42
42
  export const pikkuConsoleSetSecret = pikkuFunc({
43
+ secretBroker: true,
43
44
  tags: ['pikku'],
44
45
  description: 'Set the value of a secret',
45
46
  expose: true,
@@ -89,6 +90,7 @@ export const pikkuConsoleSetVariable = pikkuFunc({
89
90
  })
90
91
 
91
92
  export const pikkuConsoleHasSecret = pikkuFunc({
93
+ secretBroker: true,
92
94
  tags: ['pikku'],
93
95
  description: 'Check if a secret exists without reading its value',
94
96
  expose: true,
@@ -101,6 +103,7 @@ export const pikkuConsoleHasSecret = pikkuFunc({
101
103
  })
102
104
 
103
105
  export const pikkuConsoleGetSecret = pikkuFunc({
106
+ secretBroker: true,
104
107
  tags: ['pikku'],
105
108
  description: 'Get the current value of a secret',
106
109
  expose: true,
@@ -129,13 +132,7 @@ export const consoleRoutes = defineHTTPRoutes({
129
132
  },
130
133
  })
131
134
 
132
- // The console addon's functions have no authorization of their own. An app
133
- // gates the whole privileged surface (credential read/write, source editing,
134
- // package install) with a single package-scoped global permission —
135
- // addGlobalPermission([isAdmin], '@pikku/addon-console') — which is resolved in
136
- // the addon's package namespace, so it applies to every one of its functions at
137
- // once. Apps that don't register one are unaffected (no globals => allow).
138
- wireAddon({ name: 'console', package: '@pikku/addon-console' })
135
+ wireAddon({ name: 'console', package: '@pikku/addon-console', scopes: ['admin'] })
139
136
  wireHTTPRoutes({ basePath: '${globalHTTPPrefix}', routes: { console: consoleRoutes } })
140
137
  `;
141
138
  return { schemas, functions };
@@ -7,7 +7,7 @@ export const serializeFunctionTypes = (userSessionTypeImport, userSessionTypeNam
7
7
  ? nodeCategories.map((c) => `'${c}'`).join(' | ')
8
8
  : 'string';
9
9
  const workflowImport = workflowTypesImport ||
10
- `import type { TypedWorkflow, TypedScenario, TypedScenarioActors } from '../workflow/pikku-workflow-types.gen.js'`;
10
+ `import type { TypedWorkflow, TypedScenario, TypedPersonas } from '../workflow/pikku-workflow-types.gen.js'`;
11
11
  // Falls back to `string` when a project has no scopes codegen, so that
12
12
  // `scopes` stays usable rather than resolving to an unbound type name.
13
13
  const scopesImport = scopesTypeImport || `type ScopeId = string`;
@@ -15,7 +15,7 @@ export const serializeFunctionTypes = (userSessionTypeImport, userSessionTypeNam
15
15
  * Core function, middleware, and permission types for all wirings
16
16
  */
17
17
 
18
- import type { CorePikkuMiddleware, CorePermissionGroup, ListInput, ListOutput, PikkuWire, PickRequired } from '@pikku/core'
18
+ import type { CorePikkuMiddleware, CorePermissionGroup, ListInput, ListOutput, PikkuWire, PickRequired, SecretlessServices, SecretService } from '@pikku/core'
19
19
  import type { CorePikkuFunctionConfig, CorePikkuAuth, CorePikkuAuthConfig, CorePikkuPermission } from '@pikku/core/function'
20
20
  import { pikkuAuth as pikkuAuthCore } from '@pikku/core/function'
21
21
  import {
@@ -51,7 +51,20 @@ ${configTypeImport.includes('Config type not found') ? 'export type Config = any
51
51
  * why an \`if (!service)\` guard inside a function body is always dead code.
52
52
  */
53
53
  export type WiredSingletonServices = RequiredSingletonServices & SingletonServices
54
- export type WiredServices = RequiredSingletonServices & Services
54
+ export type WiredServices = SecretlessServices<RequiredSingletonServices & Services>
55
+
56
+ /** \`WiredSingletonServices\` without \`secrets\`, for auth gates. */
57
+ export type WiredAuthServices = SecretlessServices<WiredSingletonServices>
58
+
59
+ /**
60
+ * \`WiredServices\` with \`secrets\` restored, for the console's secret-admin
61
+ * functions. Reached by declaring \`secretBroker: true\` on a \`pikkuFunc\` config.
62
+ *
63
+ * Declaring it does not grant the service. The runner hands out the real
64
+ * \`SecretService\` only to the functions the inspector marks as secret brokers;
65
+ * every other function still receives the throwing accessor.
66
+ */
67
+ export type WiredSecretBrokerServices = WiredServices & { secrets: SecretService }
55
68
 
56
69
  /**
57
70
  * Inline node configuration for function definitions.
@@ -70,7 +83,7 @@ export type NodeConfig = {
70
83
  * @template In - The input type that the permission check will receive
71
84
  * @template RequiredServices - The services required for this permission check
72
85
  */
73
- export type PikkuPermission<In = unknown, RequiredServices extends Services = WiredServices> = CorePikkuPermission<In, RequiredServices, PikkuWire<In, never, false, Session>>
86
+ export type PikkuPermission<In = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices> = CorePikkuPermission<In, RequiredServices, PikkuWire<In, never, false, Session>>
74
87
 
75
88
  /**
76
89
  * Type-safe middleware definition that can access your application's services and session.
@@ -83,7 +96,7 @@ export type PikkuMiddleware<RequiredServices extends SingletonServices = WiredSi
83
96
  /**
84
97
  * Configuration object for creating a permission with metadata
85
98
  */
86
- export type PikkuPermissionConfig<In = unknown, RequiredServices extends Services = WiredServices> = {
99
+ export type PikkuPermissionConfig<In = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices> = {
87
100
  /** The permission function */
88
101
  func: PikkuPermission<In, RequiredServices>
89
102
  /** Optional human-readable name for the permission */
@@ -128,12 +141,12 @@ export const pikkuPermission = <In>(
128
141
  *
129
142
  * @template RequiredServices - The services required for this auth check
130
143
  */
131
- export type PikkuAuth<RequiredServices extends SingletonServices = WiredSingletonServices> = CorePikkuAuth<RequiredServices, Session>
144
+ export type PikkuAuth<RequiredServices extends SecretlessServices<SingletonServices> = WiredAuthServices> = CorePikkuAuth<RequiredServices, Session>
132
145
 
133
146
  /**
134
147
  * Configuration object for creating an auth permission with metadata
135
148
  */
136
- export type PikkuAuthConfig<RequiredServices extends SingletonServices = WiredSingletonServices> = CorePikkuAuthConfig<RequiredServices, Session>
149
+ export type PikkuAuthConfig<RequiredServices extends SecretlessServices<SingletonServices> = WiredAuthServices> = CorePikkuAuthConfig<RequiredServices, Session>
137
150
 
138
151
  /**
139
152
  * Factory function for creating auth-only permissions with tree-shaking support.
@@ -155,7 +168,7 @@ export type PikkuAuthConfig<RequiredServices extends SingletonServices = WiredSi
155
168
  * })
156
169
  * \\\`\\\`\\\`
157
170
  */
158
- export const pikkuAuth = <RequiredServices extends SingletonServices = WiredSingletonServices>(
171
+ export const pikkuAuth = <RequiredServices extends SecretlessServices<SingletonServices> = WiredAuthServices>(
159
172
  auth: PikkuAuth<RequiredServices> | PikkuAuthConfig<RequiredServices>
160
173
  ): PikkuPermission<any, any> => {
161
174
  return pikkuAuthCore(auth as any) as any
@@ -257,7 +270,7 @@ export const pikkuPermissionFactory = <In = any>(
257
270
  * @template In - The input type (same as the function it describes)
258
271
  * @template RequiredServices - The services required for this description function
259
272
  */
260
- export type PikkuApprovalDescription<In = unknown, RequiredServices extends Services = WiredServices> = (
273
+ export type PikkuApprovalDescription<In = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices> = (
261
274
  services: RequiredServices,
262
275
  data: In
263
276
  ) => Promise<string>
@@ -275,7 +288,7 @@ export type PikkuApprovalDescription<In = unknown, RequiredServices extends Serv
275
288
  * )
276
289
  * \`\`\`
277
290
  */
278
- export const pikkuApprovalDescription = <In = unknown, RequiredServices extends Services = WiredServices>(
291
+ export const pikkuApprovalDescription = <In = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices>(
279
292
  fn: PikkuApprovalDescription<In, RequiredServices>
280
293
  ): PikkuApprovalDescription<In, RequiredServices> => {
281
294
  return fn
@@ -293,13 +306,13 @@ export type PikkuFunctionSessionless<
293
306
  In = unknown,
294
307
  Out = never,
295
308
  RequiredWires extends keyof PikkuWire = never,
296
- RequiredServices extends Services = WiredServices
309
+ RequiredServices extends SecretlessServices<Services> = WiredServices
297
310
  > = CorePikkuFunctionSessionless<
298
311
  In,
299
312
  Out,
300
313
  RequiredServices,
301
314
  Session,
302
- PickRequired<PikkuWire<In, Out, false, Session, TypedPikkuRPC, null, any, TypedWorkflow, unknown, TypedScenario, TypedScenarioActors>, RequiredWires>
315
+ PickRequired<PikkuWire<In, Out, false, Session, TypedPikkuRPC, null, any, TypedWorkflow, unknown, TypedScenario, TypedPersonas>, RequiredWires>
303
316
  >
304
317
 
305
318
  /**
@@ -314,13 +327,13 @@ export type PikkuFunction<
314
327
  In = unknown,
315
328
  Out = never,
316
329
  RequiredWires extends keyof PikkuWire = 'session',
317
- RequiredServices extends Services = WiredServices
330
+ RequiredServices extends SecretlessServices<Services> = WiredServices
318
331
  > = CorePikkuFunction<
319
332
  In,
320
333
  Out,
321
334
  RequiredServices,
322
335
  Session,
323
- PickRequired<PikkuWire<In, Out, true, Session, TypedPikkuRPC, null, any, TypedWorkflow, unknown, TypedScenario, TypedScenarioActors>, RequiredWires>
336
+ PickRequired<PikkuWire<In, Out, true, Session, TypedPikkuRPC, null, any, TypedWorkflow, unknown, TypedScenario, TypedPersonas>, RequiredWires>
324
337
  >
325
338
 
326
339
  /**
@@ -340,7 +353,7 @@ export type PikkuFunctionConfig<
340
353
  In = unknown,
341
354
  Out = unknown,
342
355
  RequiredWires extends keyof PikkuWire = never,
343
- PikkuFunc extends PikkuFunction<In, Out, RequiredWires> | PikkuFunctionSessionless<In, Out, RequiredWires> = PikkuFunction<In, Out, RequiredWires> | PikkuFunctionSessionless<In, Out, RequiredWires>,
356
+ PikkuFunc extends PikkuFunction<In, Out, RequiredWires, any> | PikkuFunctionSessionless<In, Out, RequiredWires, any> = PikkuFunction<In, Out, RequiredWires> | PikkuFunctionSessionless<In, Out, RequiredWires>,
344
357
  InputSchema extends StandardSchemaV1 | undefined = undefined,
345
358
  OutputSchema extends StandardSchemaV1 | undefined = undefined
346
359
  > = CorePikkuFunctionConfig<PikkuFunc, PikkuPermission<In>, PikkuMiddleware, InputSchema, OutputSchema, ScopeId>
@@ -361,11 +374,12 @@ type SchemaInferred<S, Fallback = unknown> = S extends StandardSchemaV1
361
374
  export type PikkuFunctionConfigWithSchema<
362
375
  InputSchema extends StandardSchemaV1 | undefined = undefined,
363
376
  OutputSchema extends StandardSchemaV1 | undefined = undefined,
364
- RequiredWires extends keyof PikkuWire = never
377
+ RequiredWires extends keyof PikkuWire = never,
378
+ RequiredServices extends SecretlessServices<Services> = WiredServices
365
379
  > = Omit<
366
380
  CorePikkuFunctionConfig<
367
- | PikkuFunction<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires>
368
- | PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires>,
381
+ | PikkuFunction<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>
382
+ | PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>,
369
383
  CorePikkuPermission<any>,
370
384
  PikkuMiddleware,
371
385
  undefined,
@@ -375,8 +389,8 @@ export type PikkuFunctionConfigWithSchema<
375
389
  'func' | 'input' | 'output' | 'permissions' | 'approvalDescription'
376
390
  > & {
377
391
  func:
378
- | PikkuFunction<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires>
379
- | PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires>
392
+ | PikkuFunction<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>
393
+ | PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>
380
394
  input?: InputSchema
381
395
  output?: OutputSchema
382
396
  permissions?: InputSchema extends StandardSchemaV1
@@ -413,6 +427,12 @@ export type PikkuFunctionConfigWithSchema<
413
427
  * })
414
428
  * \`\`\`
415
429
  */
430
+ export function pikkuFunc<
431
+ InputSchema extends StandardSchemaV1 | undefined = undefined,
432
+ OutputSchema extends StandardSchemaV1 | undefined = undefined
433
+ >(
434
+ config: PikkuFunctionConfigWithSchema<InputSchema, OutputSchema, 'session' | 'rpc', WiredSecretBrokerServices> & { secretBroker: true }
435
+ ): PikkuFunctionConfig<InputSchema extends StandardSchemaV1 ? InferSchemaOutput<InputSchema> : unknown, OutputSchema extends StandardSchemaV1 ? InferSchemaOutput<OutputSchema> : unknown, 'session' | 'rpc'>
416
436
  export function pikkuFunc<
417
437
  InputSchema extends StandardSchemaV1 | undefined = undefined,
418
438
  OutputSchema extends StandardSchemaV1 | undefined = undefined
@@ -464,17 +484,19 @@ export const pikkuListFunc = <
464
484
  export type PikkuFunctionSessionlessConfigWithSchema<
465
485
  InputSchema extends StandardSchemaV1 | undefined = undefined,
466
486
  OutputSchema extends StandardSchemaV1 | undefined = undefined,
467
- RequiredWires extends keyof PikkuWire = never
487
+ RequiredWires extends keyof PikkuWire = never,
488
+ RequiredServices extends SecretlessServices<Services> = WiredServices
468
489
  > = Omit<
469
490
  CorePikkuFunctionConfig<
470
- PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires>
491
+ PikkuFunctionSessionless<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, RequiredWires, RequiredServices>
471
492
  >,
472
493
  'func' | 'input' | 'output' | 'permissions' | 'approvalDescription'
473
494
  > & {
474
495
  func: PikkuFunctionSessionless<
475
496
  SchemaInferred<InputSchema>,
476
497
  SchemaInferred<OutputSchema>,
477
- RequiredWires
498
+ RequiredWires,
499
+ RequiredServices
478
500
  >
479
501
  input?: InputSchema
480
502
  output?: OutputSchema
@@ -512,14 +534,15 @@ export type PikkuFunctionSessionlessConfigWithSchema<
512
534
  */
513
535
  export function pikkuSessionlessFunc<
514
536
  InputSchema extends StandardSchemaV1 | undefined = undefined,
515
- OutputSchema extends StandardSchemaV1 | undefined = undefined
537
+ OutputSchema extends StandardSchemaV1 | undefined = undefined,
538
+ RequiredServices extends SecretlessServices<Services> = WiredServices
516
539
  >(
517
- config: PikkuFunctionSessionlessConfigWithSchema<InputSchema, OutputSchema, 'session' | 'rpc'>
540
+ config: PikkuFunctionSessionlessConfigWithSchema<InputSchema, OutputSchema, 'session' | 'rpc', RequiredServices>
518
541
  ): PikkuFunctionConfig<InputSchema extends StandardSchemaV1 ? InferSchemaOutput<InputSchema> : unknown, OutputSchema extends StandardSchemaV1 ? InferSchemaOutput<OutputSchema> : unknown, 'session' | 'rpc'>
519
- export function pikkuSessionlessFunc<In, Out = unknown>(
542
+ export function pikkuSessionlessFunc<In, Out = unknown, RequiredServices extends SecretlessServices<Services> = WiredServices>(
520
543
  func:
521
- | PikkuFunctionSessionless<In, Out, 'session' | 'rpc'>
522
- | PikkuFunctionConfig<In, Out, 'session' | 'rpc'>
544
+ | PikkuFunctionSessionless<In, Out, 'session' | 'rpc', RequiredServices>
545
+ | PikkuFunctionConfig<In, Out, 'session' | 'rpc', PikkuFunctionSessionless<In, Out, 'session' | 'rpc', RequiredServices>>
523
546
  ): PikkuFunctionConfig<In, Out, 'session' | 'rpc'>
524
547
  export function pikkuSessionlessFunc(func: any) {
525
548
  return typeof func === 'function' ? { func } : func
@@ -584,6 +607,43 @@ export const ref = <Name extends keyof FlattenedRPCMap>(
584
607
  >
585
608
  }
586
609
 
610
+ /**
611
+ * Declares a capability the connected client answers, reachable from any
612
+ * \`wireChannel\` function as \`channel.remote(name, input)\`.
613
+ *
614
+ * There is no \`func\`: this side owns the contract, the client owns the body.
615
+ * The \`description\` is what a person is shown when asked to approve the call,
616
+ * so write it for them rather than for the caller.
617
+ *
618
+ * @example
619
+ * \`\`\`typescript
620
+ * export const localCheckoutOutput = z.object({ sha: z.string(), branch: z.string() })
621
+ *
622
+ * export const localCheckout = pikkuRemoteChannelFunc({
623
+ * description: 'Read the current commit and branch of your working tree',
624
+ * output: localCheckoutOutput,
625
+ * })
626
+ * \`\`\`
627
+ */
628
+ export function pikkuRemoteChannelFunc<
629
+ InputSchema extends StandardSchemaV1 | undefined = undefined,
630
+ OutputSchema extends StandardSchemaV1 | undefined = undefined
631
+ >(
632
+ config: Omit<
633
+ PikkuFunctionSessionlessConfigWithSchema<InputSchema, OutputSchema, 'session' | 'rpc'>,
634
+ 'func'
635
+ >
636
+ ): PikkuFunctionConfig<SchemaInferred<InputSchema>, SchemaInferred<OutputSchema>, 'session' | 'rpc'> {
637
+ return {
638
+ ...config,
639
+ func: async (_services: any, _data: any, _wire: any) => {
640
+ throw new Error(
641
+ \`\${config.title ?? 'This'} is a remote channel capability and has no local implementation — reach it with channel.remote() on the channel whose client exposes it.\`
642
+ )
643
+ },
644
+ } as any
645
+ }
646
+
587
647
  /**
588
648
  * Creates a Pikku config factory.
589
649
  * Use this to define your application's configuration factory.
@@ -2,16 +2,30 @@ import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
2
2
  const collectFactories = (groupMap, outputPath, packageMappings) => {
3
3
  const factories = new Map();
4
4
  for (const [, groupMeta] of groupMap.entries()) {
5
- if (groupMeta.exportName && groupMeta.isFactory) {
6
- const filePath = getFileImportRelativePath(outputPath, groupMeta.sourceFile, packageMappings);
7
- factories.set(groupMeta.exportName, {
8
- exportName: groupMeta.exportName,
9
- filePath,
10
- });
5
+ for (const registration of registrationsOf(groupMeta)) {
6
+ if (registration.exportName && registration.isFactory) {
7
+ const filePath = getFileImportRelativePath(outputPath, registration.sourceFile, packageMappings);
8
+ factories.set(registration.exportName, {
9
+ exportName: registration.exportName,
10
+ filePath,
11
+ });
12
+ }
11
13
  }
12
14
  }
13
15
  return factories;
14
16
  };
17
+ /**
18
+ * Every `add*Middleware` call recorded under one pattern or tag.
19
+ *
20
+ * A group is keyed by its pattern, and more than one file may register for the
21
+ * same one. Emitting only the primary registration meant the other file was
22
+ * never imported, so its middleware never registered — which for a session
23
+ * bridge or an auth gate fails open and fails silently.
24
+ */
25
+ const registrationsOf = (groupMeta) => [
26
+ groupMeta,
27
+ ...(groupMeta.additionalRegistrations ?? []),
28
+ ];
15
29
  export const serializeMiddlewareImports = (outputPath, middlewareState, httpState, packageMappings = {}, fullState) => {
16
30
  const serializedImports = [];
17
31
  const serializedFactoryCalls = [];
@@ -24,9 +38,11 @@ export const serializeMiddlewareImports = (outputPath, middlewareState, httpStat
24
38
  const directImports = new Set();
25
39
  const collectDirectImports = (groupMap) => {
26
40
  for (const [, groupMeta] of groupMap.entries()) {
27
- if (!groupMeta.isFactory) {
28
- const filePath = getFileImportRelativePath(outputPath, groupMeta.sourceFile, packageMappings);
29
- directImports.add(filePath);
41
+ for (const registration of registrationsOf(groupMeta)) {
42
+ if (!registration.isFactory) {
43
+ const filePath = getFileImportRelativePath(outputPath, registration.sourceFile, packageMappings);
44
+ directImports.add(filePath);
45
+ }
30
46
  }
31
47
  }
32
48
  };
@@ -1,15 +1,17 @@
1
1
  export const serializeSecretDefinitionTypes = () => {
2
- return `export { wireSecret } from '@pikku/core/secret'
2
+ return `export { defineSecret } from '@pikku/core/secret'
3
3
  export type { CoreSecret, SecretDefinitionMeta, SecretDefinitionsMeta } from '@pikku/core/secret'
4
4
  `;
5
5
  };
6
6
  export const serializeScopeDefinitionTypes = () => {
7
- return `export { wireScope } from '@pikku/core/scope'
7
+ return `export { defineScope } from '@pikku/core/scope'
8
8
  export type { CoreScopes, CoreScopeNode, FlatScope, ScopeDefinitionMeta, ScopeDefinitionsMeta } from '@pikku/core/scope'
9
+ export { defineSystemRole } from '@pikku/core/role'
10
+ export type { CoreSystemRole, CoreSystemRoles, SystemRole, SystemRoleDefinitionMeta, SystemRoleDefinitionsMeta } from '@pikku/core/role'
9
11
  `;
10
12
  };
11
13
  export const serializeVariableDefinitionTypes = () => {
12
- return `export { wireVariable } from '@pikku/core/variable'
14
+ return `export { defineVariable } from '@pikku/core/variable'
13
15
  export type { CoreVariable, VariableDefinitionMeta, VariableDefinitionsMeta } from '@pikku/core/variable'
14
16
  `;
15
17
  };
@@ -0,0 +1,7 @@
1
+ export declare const pikkuPersonas: import("#pikku").PikkuFunctionConfig<{
2
+ bootstrap?: boolean;
3
+ }, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{
4
+ bootstrap?: boolean;
5
+ }, void, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<{
6
+ bootstrap?: boolean;
7
+ }, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;
@@ -0,0 +1,43 @@
1
+ import { pikkuSessionlessFunc } from '#pikku';
2
+ import { writeFileInDir } from '../../../utils/file-writer.js';
3
+ import { getFileImportRelativePath } from '../../../utils/file-import-path.js';
4
+ import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
5
+ import { serializePersonasTypes } from './serialize-personas-types.js';
6
+ import { personaEnvironmentErrors, validateAndBuildPersonasMeta, } from '@pikku/core/persona';
7
+ export const pikkuPersonas = pikkuSessionlessFunc({
8
+ func: async ({ logger, config, getInspectorState }, data) => {
9
+ const { personasFile, personasMetaJsonFile, rolesFile, packageMappings } = config;
10
+ if (!personasFile) {
11
+ return;
12
+ }
13
+ // Same cold-start reasoning as Scopes and Roles: on a bare .pikku this
14
+ // runs before the app's own types exist, so it takes the zero state. The
15
+ // file only has to exist so a persona file can import definePersonas.
16
+ const bootstrap = data?.bootstrap ?? false;
17
+ const state = await getInspectorState(false, bootstrap, bootstrap);
18
+ const environments = config.environments ?? {};
19
+ // Before anything is written. A persona that may not run where it says it
20
+ // runs is a declaration to fix, not a file to generate — and generating
21
+ // it anyway would leave a `.pikku` that typechecks while lying.
22
+ const errors = state.personas.definitions.flatMap((persona) => personaEnvironmentErrors(persona.id, persona, environments));
23
+ if (errors.length) {
24
+ throw new Error(errors.join('\n'));
25
+ }
26
+ const content = serializePersonasTypes({
27
+ definitions: state.personas.definitions,
28
+ rolesImportPath: getFileImportRelativePath(personasFile, rolesFile, packageMappings),
29
+ environmentNames: Object.keys(environments),
30
+ });
31
+ await writeFileInDir(logger, personasFile, content);
32
+ if (personasMetaJsonFile) {
33
+ const meta = validateAndBuildPersonasMeta(state.personas.definitions);
34
+ await writeFileInDir(logger, personasMetaJsonFile, JSON.stringify(meta, null, 2));
35
+ }
36
+ },
37
+ middleware: [
38
+ logCommandInfoAndTime({
39
+ commandStart: 'Creating PikkuPersonas types',
40
+ commandEnd: 'Created PikkuPersonas types',
41
+ }),
42
+ ],
43
+ });
@@ -0,0 +1,18 @@
1
+ import type { PersonaDefinitions } from '@pikku/core/persona';
2
+ export interface SerializePersonasOptions {
3
+ definitions: PersonaDefinitions;
4
+ /** Relative import path to the generated roles file. */
5
+ rolesImportPath: string;
6
+ /** Keys of `environments` in pikku.config.json. */
7
+ environmentNames: string[];
8
+ }
9
+ /**
10
+ * Generates the `PersonaId` union and a `definePersonas` whose `roles` are
11
+ * checked against the declared system roles.
12
+ *
13
+ * The wrapper is why this is generated rather than re-exported: `roles` typed
14
+ * as `string[]` would let a persona name a role nobody declared, and the
15
+ * failure — a scatter of 403s in a run days later — looks nothing like the
16
+ * mistake. Typed as `SystemRoleName[]`, it is a red squiggle in the editor.
17
+ */
18
+ export declare const serializePersonasTypes: ({ definitions, rolesImportPath, environmentNames, }: SerializePersonasOptions) => string;
@@ -0,0 +1,76 @@
1
+ const quote = (value) => `'${value.replace(/'/g, "\\'")}'`;
2
+ /**
3
+ * Generates the `PersonaId` union and a `definePersonas` whose `roles` are
4
+ * checked against the declared system roles.
5
+ *
6
+ * The wrapper is why this is generated rather than re-exported: `roles` typed
7
+ * as `string[]` would let a persona name a role nobody declared, and the
8
+ * failure — a scatter of 403s in a run days later — looks nothing like the
9
+ * mistake. Typed as `SystemRoleName[]`, it is a red squiggle in the editor.
10
+ */
11
+ export const serializePersonasTypes = ({ definitions, rolesImportPath, environmentNames, }) => {
12
+ const ids = [...new Set(definitions.map((d) => d.id))].sort();
13
+ const environmentUnion = environmentNames.length > 0
14
+ ? `\n${[...environmentNames].sort().map((name) => ` | ${quote(name)}`).join('\n')}`
15
+ : ' never';
16
+ const union = ids.length > 0
17
+ ? `\n${ids.map((id) => ` | ${quote(id)}`).join('\n')}`
18
+ : ' never';
19
+ const runnable = definitions
20
+ .filter((d) => d.runnable)
21
+ .map((d) => d.id)
22
+ .sort();
23
+ const runnableUnion = runnable.length > 0
24
+ ? `\n${runnable.map((id) => ` | ${quote(id)}`).join('\n')}`
25
+ : ' never';
26
+ return `/**
27
+ * This file was generated by the @pikku/cli
28
+ */
29
+ import { definePersonas as definePersonasCore } from '@pikku/core/persona'
30
+ import type { CorePersona, PersonaMeta, PersonasMeta } from '@pikku/core/persona'
31
+ import type { SystemRoleName } from '${rolesImportPath}'
32
+ import definitions from './pikku-personas-meta.gen.json' with { type: 'json' }
33
+
34
+ /** Every declared persona. */
35
+ export type PersonaId =${union}
36
+
37
+ /**
38
+ * The personas a virtual user can actually be.
39
+ *
40
+ * Excludes anyone whose only login is a provider account — driving a consent
41
+ * screen needs a human — and anyone declared \`runnable: false\`, who exists to
42
+ * be acted upon rather than to act.
43
+ */
44
+ export type RunnablePersonaId =${runnableUnion}
45
+
46
+ /** Every environment configured in pikku.config.json. */
47
+ export type EnvironmentName =${environmentUnion}
48
+
49
+ /**
50
+ * A persona whose roles are checked against \`defineSystemRole\` and whose
51
+ * environments are checked against the config.
52
+ *
53
+ * Omitting \`environments\` means every environment except the ones flagged
54
+ * \`production: true\`. Naming a production one additionally requires
55
+ * \`disposition: 'accountable'\`, which the type cannot express and \`pikku\`
56
+ * refuses at build time.
57
+ */
58
+ export type TypedPersona = Omit<CorePersona, 'roles' | 'environments'> & {
59
+ roles?: SystemRoleName[]
60
+ environments?: EnvironmentName[]
61
+ }
62
+
63
+ /**
64
+ * Declare the people who use this application.
65
+ *
66
+ * A persona while running is a virtual user; there is no second declaration.
67
+ */
68
+ export const definePersonas = (personas: Record<string, TypedPersona>): void =>
69
+ definePersonasCore(personas)
70
+
71
+ /** Declared personas, keyed by id. Read by the console and \`pikku persona\`. */
72
+ export const PERSONAS: PersonasMeta = definitions as unknown as PersonasMeta
73
+
74
+ export const PERSONA_LIST: PersonaMeta[] = Object.values(PERSONAS)
75
+ `;
76
+ };
@@ -4,6 +4,7 @@ import { writeFileInDir } from '../../../utils/file-writer.js';
4
4
  import { logCommandInfoAndTime } from '../../../middleware/log-command-info-and-time.js';
5
5
  import { removeLegacyScaffoldFile } from '../../../utils/remove-legacy-scaffold-file.js';
6
6
  import { serializeEventsScaffold } from './serialize-events-scaffold.js';
7
+ import { resolveScaffoldFeature } from '../../../utils/resolve-scaffold-feature.js';
7
8
  export const pikkuEventsScaffold = pikkuSessionlessFunc({
8
9
  func: async ({ logger, config }) => {
9
10
  if (!config.scaffold?.events ||
@@ -15,7 +16,7 @@ export const pikkuEventsScaffold = pikkuSessionlessFunc({
15
16
  });
16
17
  return false;
17
18
  }
18
- const authRequired = config.scaffold.events === 'auth';
19
+ const authRequired = resolveScaffoldFeature('events', config.scaffold.events).auth;
19
20
  const pikkuTypesImportPath = getFileImportRelativePath(config.eventsChannelFile, config.typesDeclarationFile, config.packageMappings);
20
21
  const { schemas, functions } = serializeEventsScaffold(authRequired, pikkuTypesImportPath);
21
22
  await writeFileInDir(logger, config.eventsSchemasFile, schemas);
@@ -0,0 +1,7 @@
1
+ export declare const pikkuRoles: import("#pikku").PikkuFunctionConfig<{
2
+ bootstrap?: boolean;
3
+ }, void, "rpc" | "session", import("#pikku").PikkuFunctionSessionless<{
4
+ bootstrap?: boolean;
5
+ }, void, "rpc" | "session", import("#pikku").WiredServices> | import("#pikku").PikkuFunction<{
6
+ bootstrap?: boolean;
7
+ }, void, "rpc" | "session", import("#pikku").WiredServices>, undefined, undefined>;