@pikku/core 0.12.97 → 0.12.98
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/classification/data-classification.d.ts +10 -0
- package/dist/classification/data-lock.d.ts +80 -0
- package/dist/classification/data-lock.js +146 -0
- package/dist/classification/index.d.ts +1 -0
- package/dist/classification/index.js +1 -0
- package/dist/classification/key-ids.d.ts +2 -0
- package/dist/classification/key-ids.js +2 -0
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/index.js +1 -1
- package/dist/middleware/require-unlocked.d.ts +23 -0
- package/dist/middleware/require-unlocked.js +21 -0
- package/dist/wirings/data-lock/data-lock-wiring.d.ts +40 -0
- package/dist/wirings/data-lock/data-lock-wiring.js +77 -0
- package/dist/wirings/data-lock/index.d.ts +9 -0
- package/dist/wirings/data-lock/index.js +8 -0
- package/dist/wirings/virtual-user/virtual-user-scaffold.d.ts +7 -1
- package/dist/wirings/virtual-user/virtual-user-scaffold.js +25 -3
- package/package.json +1 -1
- package/src/classification/data-classification.ts +10 -0
- package/src/classification/index.ts +2 -0
- package/src/classification/key-ids.ts +2 -0
- package/src/middleware/index.ts +0 -1
- package/src/public-surface.json +1 -1
- package/src/wirings/virtual-user/virtual-user-scaffold.test.ts +59 -0
- package/src/wirings/virtual-user/virtual-user-scaffold.ts +37 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -244,6 +244,65 @@ describe('startVirtualUserRun', () => {
|
|
|
244
244
|
assert.equal(started[0].disposition, 'accountable')
|
|
245
245
|
})
|
|
246
246
|
|
|
247
|
+
// The case NODE_ENV cannot answer: a staging environment that is a production
|
|
248
|
+
// mirror runs NODE_ENV=production too, and refusing every disposition there
|
|
249
|
+
// refuses them on the one environment they exist to be used on.
|
|
250
|
+
test('a non-production environment allows a probing disposition', async () => {
|
|
251
|
+
const { store, started } = runStore()
|
|
252
|
+
await startVirtualUserRun({
|
|
253
|
+
store,
|
|
254
|
+
personas,
|
|
255
|
+
config: { nodeEnv: 'production' },
|
|
256
|
+
environments: { staging: {}, production: { production: true } },
|
|
257
|
+
environment: 'staging',
|
|
258
|
+
persona: 'susan',
|
|
259
|
+
disposition: 'adversarial',
|
|
260
|
+
})
|
|
261
|
+
assert.equal(started[0].disposition, 'adversarial')
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
test('the configured production environment still refuses one', async () => {
|
|
265
|
+
const { store, started } = runStore()
|
|
266
|
+
await assert.rejects(
|
|
267
|
+
startVirtualUserRun({
|
|
268
|
+
store,
|
|
269
|
+
personas,
|
|
270
|
+
config: { nodeEnv: 'development' },
|
|
271
|
+
environments: { staging: {}, production: { production: true } },
|
|
272
|
+
environment: 'production',
|
|
273
|
+
persona: 'susan',
|
|
274
|
+
disposition: 'adversarial',
|
|
275
|
+
}),
|
|
276
|
+
/Only the 'accountable' disposition may run against production/
|
|
277
|
+
)
|
|
278
|
+
assert.equal(started.length, 0)
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
// An environment nobody can name is one whose data nobody can vouch for.
|
|
282
|
+
// PIKKU_ENV is cleared rather than passed as undefined: it is the default the
|
|
283
|
+
// parameter falls back to, so leaving it set would test the wrong thing.
|
|
284
|
+
test('an unresolved environment is treated as production', async () => {
|
|
285
|
+
const { store, started } = runStore()
|
|
286
|
+
const pikkuEnv = process.env.PIKKU_ENV
|
|
287
|
+
delete process.env.PIKKU_ENV
|
|
288
|
+
try {
|
|
289
|
+
await assert.rejects(
|
|
290
|
+
startVirtualUserRun({
|
|
291
|
+
store,
|
|
292
|
+
personas,
|
|
293
|
+
config: { nodeEnv: 'development' },
|
|
294
|
+
environments: { staging: {}, production: { production: true } },
|
|
295
|
+
persona: 'susan',
|
|
296
|
+
disposition: 'adversarial',
|
|
297
|
+
}),
|
|
298
|
+
/Only the 'accountable' disposition may run against production/
|
|
299
|
+
)
|
|
300
|
+
} finally {
|
|
301
|
+
if (pikkuEnv !== undefined) process.env.PIKKU_ENV = pikkuEnv
|
|
302
|
+
}
|
|
303
|
+
assert.equal(started.length, 0)
|
|
304
|
+
})
|
|
305
|
+
|
|
247
306
|
test('refuses a persona that is declared as acted upon', async () => {
|
|
248
307
|
const { store, started } = runStore()
|
|
249
308
|
await assert.rejects(
|
|
@@ -11,6 +11,7 @@ import { prepareVirtualUserRun } from './prepare-virtual-user-run.js'
|
|
|
11
11
|
import { runVirtualUser as runVirtualUserEngine } from './run-virtual-user.js'
|
|
12
12
|
import { personaVirtualUserTarget } from './virtual-user-target.js'
|
|
13
13
|
import type { SchemaMap } from './virtual-user-derive.js'
|
|
14
|
+
import type { PersonaEnvironment } from '../persona/persona-environments.js'
|
|
14
15
|
import { PRODUCTION_DISPOSITION } from './virtual-user.types.js'
|
|
15
16
|
import type {
|
|
16
17
|
StepRecord,
|
|
@@ -160,8 +161,13 @@ export interface StartVirtualUserRunParams {
|
|
|
160
161
|
/**
|
|
161
162
|
* The app's config, read only for `nodeEnv` — structural because an
|
|
162
163
|
* application's Config is its own interface and need not declare it at all.
|
|
164
|
+
* The fallback signal, used only by a project that configures no environments.
|
|
163
165
|
*/
|
|
164
166
|
config: { nodeEnv?: string } | undefined
|
|
167
|
+
/** `environments` from pikku.config.json, as generated beside the personas. */
|
|
168
|
+
environments?: Readonly<Record<string, PersonaEnvironment>>
|
|
169
|
+
/** Which of them this process is. Defaults to `PIKKU_ENV`. */
|
|
170
|
+
environment?: string
|
|
165
171
|
persona: string
|
|
166
172
|
disposition?: string
|
|
167
173
|
seed?: number
|
|
@@ -181,6 +187,33 @@ export interface StartedVirtualUserRun {
|
|
|
181
187
|
memory: Record<string, string>
|
|
182
188
|
}
|
|
183
189
|
|
|
190
|
+
/**
|
|
191
|
+
* Whether this process is running against production, for the disposition rule.
|
|
192
|
+
*
|
|
193
|
+
* The configured environment wins over `NODE_ENV` because they answer different
|
|
194
|
+
* questions. A deployment whose staging is a production *mirror* runs
|
|
195
|
+
* `NODE_ENV=production` there too — keying on it refuses every disposition on
|
|
196
|
+
* the one environment they exist to be used on. `PIKKU_ENV` names which of the
|
|
197
|
+
* configured environments this is, which is the question actually being asked,
|
|
198
|
+
* and it is the same signal `personaEnvironmentRefusal` already checks at
|
|
199
|
+
* sign-in.
|
|
200
|
+
*
|
|
201
|
+
* Unresolved is treated as production: an environment nobody can name is one
|
|
202
|
+
* whose data nobody can vouch for. `NODE_ENV` remains the answer only for a
|
|
203
|
+
* project that configures no environments at all, which has no production
|
|
204
|
+
* environment declared for this to be wrong about.
|
|
205
|
+
*/
|
|
206
|
+
const isProductionRun = (
|
|
207
|
+
config: { nodeEnv?: string } | undefined,
|
|
208
|
+
environments: Readonly<Record<string, PersonaEnvironment>> | undefined,
|
|
209
|
+
environment: string | undefined
|
|
210
|
+
): boolean => {
|
|
211
|
+
if (!environments || Object.keys(environments).length === 0) {
|
|
212
|
+
return config?.nodeEnv === 'production'
|
|
213
|
+
}
|
|
214
|
+
return environment ? Boolean(environments[environment]?.production) : true
|
|
215
|
+
}
|
|
216
|
+
|
|
184
217
|
/**
|
|
185
218
|
* Resolves a request against the declaration and records the run.
|
|
186
219
|
*
|
|
@@ -192,6 +225,8 @@ export const startVirtualUserRun = async ({
|
|
|
192
225
|
store,
|
|
193
226
|
personas,
|
|
194
227
|
config,
|
|
228
|
+
environments,
|
|
229
|
+
environment = process.env.PIKKU_ENV,
|
|
195
230
|
persona: personaId,
|
|
196
231
|
disposition: requested,
|
|
197
232
|
seed: requestedSeed,
|
|
@@ -210,8 +245,8 @@ export const startVirtualUserRun = async ({
|
|
|
210
245
|
// does wrong, which is not a thing to do to real customers' data. Checked
|
|
211
246
|
// against the effective disposition, so an override cannot smuggle one in.
|
|
212
247
|
if (
|
|
213
|
-
|
|
214
|
-
|
|
248
|
+
disposition !== PRODUCTION_DISPOSITION &&
|
|
249
|
+
isProductionRun(config, environments, environment)
|
|
215
250
|
) {
|
|
216
251
|
throw new Error(
|
|
217
252
|
`Only the '${PRODUCTION_DISPOSITION}' disposition may run against production; "${personaId}" is ${disposition}`
|