@cosmicdrift/kumiko-framework 0.269.1 → 0.270.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/package.json +3 -3
- package/src/__tests__/anonymous-access.integration.test.ts +1 -1
- package/src/__tests__/error-contract.integration.test.ts +1 -1
- package/src/__tests__/fixtures/migrate-db-raw/global-fetch.expected.ts +9 -0
- package/src/__tests__/fixtures/migrate-db-raw/global-fetch.input.ts +10 -0
- package/src/__tests__/fixtures/migrate-db-raw/global-select.expected.ts +6 -0
- package/src/__tests__/fixtures/migrate-db-raw/global-select.input.ts +12 -0
- package/src/__tests__/fixtures/migrate-db-raw/import-pruning.expected.ts +12 -0
- package/src/__tests__/fixtures/migrate-db-raw/import-pruning.input.ts +12 -0
- package/src/__tests__/fixtures/migrate-db-raw/manual-only.expected.ts +26 -0
- package/src/__tests__/fixtures/migrate-db-raw/manual-only.input.ts +26 -0
- package/src/__tests__/fixtures/migrate-db-raw/own-tenant-const-shorthand.expected.ts +10 -0
- package/src/__tests__/fixtures/migrate-db-raw/own-tenant-const-shorthand.input.ts +11 -0
- package/src/__tests__/fixtures/migrate-db-raw/own-tenant-event.expected.ts +9 -0
- package/src/__tests__/fixtures/migrate-db-raw/own-tenant-event.input.ts +15 -0
- package/src/__tests__/fixtures/migrate-open-to-all/manual-only.expected.ts +16 -0
- package/src/__tests__/fixtures/migrate-open-to-all/manual-only.input.ts +16 -0
- package/src/__tests__/fixtures/migrate-open-to-all/test-nested-shorthand.expected.ts +12 -0
- package/src/__tests__/fixtures/migrate-open-to-all/test-nested-shorthand.input.ts +12 -0
- package/src/__tests__/fixtures/migrate-open-to-all/test-simple.expected.ts +7 -0
- package/src/__tests__/fixtures/migrate-open-to-all/test-simple.input.ts +7 -0
- package/src/__tests__/full-stack.integration.test.ts +2 -2
- package/src/__tests__/migrate-db-raw-codemod.test.ts +132 -0
- package/src/__tests__/migrate-open-to-all-codemod.test.ts +84 -0
- package/src/__tests__/transition-guard.integration.test.ts +7 -7
- package/src/__tests__/upgrade-cli.test.ts +54 -0
- package/src/api/__tests__/api.test.ts +2 -2
- package/src/api/__tests__/body-limit.test.ts +1 -1
- package/src/api/__tests__/pii-leak-guard.integration.test.ts +2 -2
- package/src/api/__tests__/request-locale.integration.test.ts +1 -1
- package/src/api/__tests__/server-error-logging.test.ts +1 -1
- package/src/changes.json +10 -2
- package/src/db/__tests__/list-filter-field-access.integration.test.ts +1 -1
- package/src/derivatives/__tests__/derivatives-context.integration.test.ts +2 -2
- package/src/engine/__tests__/boot-validator-dashboard.test.ts +5 -5
- package/src/engine/__tests__/boot-validator-pii-retention.test.ts +1 -1
- package/src/engine/__tests__/boot-validator-projection-list.test.ts +17 -17
- package/src/engine/__tests__/boot-validator-query-output-schema.test.ts +18 -18
- package/src/engine/__tests__/boot-validator-query-refs.test.ts +3 -3
- package/src/engine/__tests__/boot-validator-s0-integration.test.ts +2 -2
- package/src/engine/__tests__/boot-validator.test.ts +18 -18
- package/src/engine/__tests__/build-app-schema.test.ts +10 -6
- package/src/engine/__tests__/build-config-feature-schema-secrets.test.ts +48 -0
- package/src/engine/__tests__/build-config-feature-schema.test.ts +34 -5
- package/src/engine/__tests__/engine.test.ts +39 -25
- package/src/engine/__tests__/entity-handlers.test.ts +19 -8
- package/src/engine/__tests__/entity-presave-wiring.integration.test.ts +2 -2
- package/src/engine/__tests__/extends-registrar.test.ts +3 -3
- package/src/engine/__tests__/feature-crud-shorthand.test.ts +9 -3
- package/src/engine/__tests__/feature-crud-verb-access.integration.test.ts +1 -1
- package/src/engine/__tests__/hook-phases.test.ts +5 -5
- package/src/engine/__tests__/lifecycle-hooks.test.ts +9 -3
- package/src/engine/__tests__/multiselect-filter.integration.test.ts +1 -1
- package/src/engine/__tests__/post-query-hook.test.ts +6 -2
- package/src/engine/__tests__/projection-detail-actions.test.ts +2 -2
- package/src/engine/__tests__/projection-detail-singleton.test.ts +3 -3
- package/src/engine/__tests__/projection-detail-tabs.test.ts +3 -3
- package/src/engine/__tests__/projection-list-filter.integration.test.ts +1 -1
- package/src/engine/__tests__/registry.test.ts +19 -13
- package/src/engine/__tests__/screen.test.ts +26 -20
- package/src/engine/boot-validator/__tests__/access-declarations.test.ts +5 -4
- package/src/engine/boot-validator/__tests__/parent-ref.test.ts +18 -6
- package/src/engine/boot-validator/access-declarations.ts +3 -5
- package/src/engine/boot-validator/nav.ts +4 -3
- package/src/engine/build-config-feature-schema.ts +9 -2
- package/src/engine/entity-handlers.ts +1 -1
- package/src/engine/feature-ast/__tests__/canonical-form.test.ts +3 -1
- package/src/engine/feature-ast/__tests__/parse-happy-path.test.ts +2 -2
- package/src/engine/feature-ast/__tests__/parse.test.ts +106 -4
- package/src/engine/feature-ast/__tests__/patcher.test.ts +3 -3
- package/src/engine/feature-ast/__tests__/read-optional-access-rule.test.ts +4 -4
- package/src/engine/feature-ast/__tests__/render-roundtrip.test.ts +5 -1
- package/src/engine/feature-ast/extractors/handlers.ts +16 -2
- package/src/engine/feature-ast/extractors/hooks.ts +25 -4
- package/src/engine/feature-ast/patcher.ts +15 -3
- package/src/engine/feature-ast/patterns.ts +4 -0
- package/src/engine/feature-ast/render.ts +3 -0
- package/src/engine/pattern-library/shared-fields.ts +7 -3
- package/src/entrypoint/__tests__/entrypoint-attach-dispatcher.integration.test.ts +1 -1
- package/src/entrypoint/__tests__/entrypoint-job-wiring.integration.test.ts +3 -3
- package/src/entrypoint/__tests__/split-deploy.integration.test.ts +1 -1
- package/src/es-ops/__tests__/runner.integration.test.ts +2 -2
- package/src/jobs/__tests__/job-event-trigger.integration.test.ts +2 -2
- package/src/jobs/__tests__/job-multi-trigger.integration.test.ts +2 -2
- package/src/jobs/__tests__/jobs.integration.test.ts +1 -1
- package/src/observability/__tests__/observability.integration.test.ts +7 -7
- package/src/pipeline/__tests__/archive-stream.integration.test.ts +2 -2
- package/src/pipeline/__tests__/dispatcher.test.ts +15 -15
- package/src/pipeline/__tests__/lifecycle-pipeline.test.ts +10 -10
- package/src/pipeline/__tests__/load-aggregate-query.integration.test.ts +1 -1
- package/src/pipeline/__tests__/post-query-hook.integration.test.ts +3 -3
- package/src/pipeline/__tests__/query-projection.integration.test.ts +3 -3
- package/src/scripts/codemod/migrate-db-raw.ts +397 -0
- package/src/scripts/codemod/migrate-open-to-all.ts +248 -0
- package/src/secrets/__tests__/contains-secret.test.ts +5 -5
- package/src/stack/__tests__/request-helper.integration.test.ts +3 -3
- package/src/stack/__tests__/setup-test-stack-jobs.integration.test.ts +1 -1
- package/src/testing/__tests__/e2e-generator.test.ts +19 -5
|
@@ -33,7 +33,7 @@ const wiringFeature = defineFeature("wiring", (r) => {
|
|
|
33
33
|
isSuccess: true as const,
|
|
34
34
|
data: { id: 1, sku: event.payload.sku },
|
|
35
35
|
}),
|
|
36
|
-
{ access: { openToAll:
|
|
36
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
37
37
|
);
|
|
38
38
|
r.job(
|
|
39
39
|
"record-order",
|
|
@@ -57,7 +57,7 @@ const mixedLaneFeature = defineFeature("mixed", (r) => {
|
|
|
57
57
|
isSuccess: true as const,
|
|
58
58
|
data: { id: 1, msg: event.payload.msg },
|
|
59
59
|
}),
|
|
60
|
-
{ access: { openToAll:
|
|
60
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
61
61
|
);
|
|
62
62
|
r.job(
|
|
63
63
|
"handle-on-worker",
|
|
@@ -240,7 +240,7 @@ const featureGateJobFeature = defineFeature("featuregate", (r) => {
|
|
|
240
240
|
isSuccess: true as const,
|
|
241
241
|
data: { id: 1, msg: event.payload.msg },
|
|
242
242
|
}),
|
|
243
|
-
{ access: { openToAll:
|
|
243
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
244
244
|
);
|
|
245
245
|
r.job(
|
|
246
246
|
"record-features",
|
|
@@ -57,7 +57,7 @@ const workerWriteFeature = defineFeature("workerWrite", (r) => {
|
|
|
57
57
|
});
|
|
58
58
|
return { isSuccess: true as const, data: { note: event.payload.note } };
|
|
59
59
|
},
|
|
60
|
-
{ access: { openToAll:
|
|
60
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
61
61
|
);
|
|
62
62
|
r.multiStreamProjection({
|
|
63
63
|
name: "consume-notes",
|
|
@@ -58,7 +58,7 @@ const seedTestFeature = defineFeature("esopstest", (r) => {
|
|
|
58
58
|
"probe:create",
|
|
59
59
|
z.object({ label: z.string().min(1) }),
|
|
60
60
|
async (event, ctx) => probeExecutor.create(event.payload, event.user, ctx.db),
|
|
61
|
-
{ access: { openToAll:
|
|
61
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
62
62
|
);
|
|
63
63
|
r.writeHandler(
|
|
64
64
|
"probe:fail",
|
|
@@ -70,7 +70,7 @@ const seedTestFeature = defineFeature("esopstest", (r) => {
|
|
|
70
70
|
currentVersion: 2,
|
|
71
71
|
});
|
|
72
72
|
},
|
|
73
|
-
{ access: { openToAll:
|
|
73
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
74
74
|
);
|
|
75
75
|
// Role-gated handler (no openToAll): the bare system actor has no bypass
|
|
76
76
|
// for explicit role gates — only systemWriteAs' extraRoles reaches it.
|
|
@@ -26,7 +26,7 @@ const ordersFeature = defineFeature("orders", (r) => {
|
|
|
26
26
|
data: { id: 1, product: event.payload.product, amount: event.payload.amount },
|
|
27
27
|
};
|
|
28
28
|
},
|
|
29
|
-
{ access: { openToAll:
|
|
29
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
30
30
|
);
|
|
31
31
|
});
|
|
32
32
|
|
|
@@ -51,7 +51,7 @@ const analyticsFeature = defineFeature("analytics", (r) => {
|
|
|
51
51
|
isSuccess: true as const,
|
|
52
52
|
data: null,
|
|
53
53
|
}),
|
|
54
|
-
{ access: { openToAll:
|
|
54
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
55
55
|
);
|
|
56
56
|
|
|
57
57
|
r.job("trackOrder", { trigger: { on: "orders:write:orders:create" } }, async (payload) => {
|
|
@@ -27,13 +27,13 @@ const orderFeature = defineFeature("multi", (r) => {
|
|
|
27
27
|
"order:open",
|
|
28
28
|
z.object({ id: z.string() }),
|
|
29
29
|
async (event) => ({ isSuccess: true, data: { id: event.payload.id } }),
|
|
30
|
-
{ access: { openToAll:
|
|
30
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
31
31
|
);
|
|
32
32
|
r.writeHandler(
|
|
33
33
|
"order:cancel",
|
|
34
34
|
z.object({ id: z.string() }),
|
|
35
35
|
async (event) => ({ isSuccess: true, data: { id: event.payload.id } }),
|
|
36
|
-
{ access: { openToAll:
|
|
36
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
37
37
|
);
|
|
38
38
|
r.job(
|
|
39
39
|
"fanout",
|
|
@@ -119,7 +119,7 @@ const testFeature = defineFeature("test", (r) => {
|
|
|
119
119
|
"capped-event",
|
|
120
120
|
z.object({ n: z.number() }),
|
|
121
121
|
async (event) => ({ isSuccess: true, data: { n: event.payload.n } }),
|
|
122
|
-
{ access: { openToAll:
|
|
122
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
123
123
|
);
|
|
124
124
|
// Event-triggered twin — exercises handleEvent's maxPerTenant guard
|
|
125
125
|
// (dispatch and handleEvent share isOverPerTenantLimit).
|
|
@@ -33,7 +33,7 @@ const productFeature = defineFeature("product", (r) => {
|
|
|
33
33
|
ctx.metrics.inc("tracked_total", { kind: event.payload.kind });
|
|
34
34
|
return { isSuccess: true, data: { ok: true } };
|
|
35
35
|
},
|
|
36
|
-
{ access: { openToAll:
|
|
36
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
37
37
|
);
|
|
38
38
|
});
|
|
39
39
|
|
|
@@ -44,7 +44,7 @@ const errorFeature = defineFeature("err", (r) => {
|
|
|
44
44
|
async () => {
|
|
45
45
|
throw new Error("boom from handler");
|
|
46
46
|
},
|
|
47
|
-
{ access: { openToAll:
|
|
47
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
48
48
|
);
|
|
49
49
|
});
|
|
50
50
|
|
|
@@ -90,7 +90,7 @@ const todoFeature = defineFeature("todo", (r) => {
|
|
|
90
90
|
},
|
|
91
91
|
};
|
|
92
92
|
},
|
|
93
|
-
{ access: { openToAll:
|
|
93
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
94
94
|
);
|
|
95
95
|
|
|
96
96
|
r.hook("postSave", "create", async (_save: SaveContext) => {
|
|
@@ -288,7 +288,7 @@ describe("Observability (integration) — Redis wrapper", () => {
|
|
|
288
288
|
await ctx.redis.get("session:abc123:token");
|
|
289
289
|
return { isSuccess: true, data: { ok: true } };
|
|
290
290
|
},
|
|
291
|
-
{ access: { openToAll:
|
|
291
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
292
292
|
);
|
|
293
293
|
});
|
|
294
294
|
|
|
@@ -352,7 +352,7 @@ describe("Observability (integration) — Pino trace bridge", () => {
|
|
|
352
352
|
ctx.log?.info(event.payload.msg, { custom: "field" });
|
|
353
353
|
return { isSuccess: true, data: { ok: true } };
|
|
354
354
|
},
|
|
355
|
-
{ access: { openToAll:
|
|
355
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
356
356
|
);
|
|
357
357
|
});
|
|
358
358
|
|
|
@@ -581,7 +581,7 @@ const consumerAFeature = defineFeature("consumer-a", (r) => {
|
|
|
581
581
|
recordSharedCall(ctx);
|
|
582
582
|
return { isSuccess: true, data: { ok: true } };
|
|
583
583
|
},
|
|
584
|
-
{ access: { openToAll:
|
|
584
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
585
585
|
);
|
|
586
586
|
});
|
|
587
587
|
|
|
@@ -594,7 +594,7 @@ const consumerBFeature = defineFeature("consumer-b", (r) => {
|
|
|
594
594
|
ctx.metricsFor("unregistered-lib").inc("never_total");
|
|
595
595
|
return { isSuccess: true, data: { ok: true } };
|
|
596
596
|
},
|
|
597
|
-
{ access: { openToAll:
|
|
597
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
598
598
|
);
|
|
599
599
|
});
|
|
600
600
|
|
|
@@ -109,14 +109,14 @@ const archFeature = defineFeature("archtest", (r) => {
|
|
|
109
109
|
"item:events",
|
|
110
110
|
z.object({ id: z.uuid() }),
|
|
111
111
|
async (query, ctx) => ctx.loadAggregate(query.payload.id),
|
|
112
|
-
{ access: { openToAll:
|
|
112
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
113
113
|
);
|
|
114
114
|
|
|
115
115
|
r.queryHandler(
|
|
116
116
|
"item:is-archived",
|
|
117
117
|
z.object({ id: z.uuid() }),
|
|
118
118
|
async (query, ctx) => ctx.isStreamArchived(query.payload.id),
|
|
119
|
-
{ access: { openToAll:
|
|
119
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
120
120
|
);
|
|
121
121
|
});
|
|
122
122
|
|
|
@@ -33,7 +33,7 @@ const echoFeature = defineFeature("echo", (r) => {
|
|
|
33
33
|
items: [],
|
|
34
34
|
search: query.payload.search,
|
|
35
35
|
}),
|
|
36
|
-
{ access: { openToAll:
|
|
36
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
37
37
|
);
|
|
38
38
|
|
|
39
39
|
r.streamHandler(
|
|
@@ -137,7 +137,7 @@ describe("dispatcher.write", () => {
|
|
|
137
137
|
z.object({ name: z.string() }),
|
|
138
138
|
async (event) => ({ isSuccess: true, data: { name: event.payload.name } }),
|
|
139
139
|
{
|
|
140
|
-
access: { openToAll:
|
|
140
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
141
141
|
rateLimit: { per: "ip+handler", limit: 3, windowSeconds: 60 },
|
|
142
142
|
},
|
|
143
143
|
);
|
|
@@ -168,7 +168,7 @@ describe("dispatcher.write", () => {
|
|
|
168
168
|
z.object({ name: z.string() }),
|
|
169
169
|
async (event) => ({ isSuccess: true, data: { name: event.payload.name } }),
|
|
170
170
|
{
|
|
171
|
-
access: { openToAll:
|
|
171
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
172
172
|
rateLimit: { per: "user", limit: 3, windowSeconds: 60 },
|
|
173
173
|
},
|
|
174
174
|
);
|
|
@@ -428,7 +428,7 @@ describe("dispatcher.stream", () => {
|
|
|
428
428
|
yield { i };
|
|
429
429
|
}
|
|
430
430
|
},
|
|
431
|
-
{ access: { openToAll:
|
|
431
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
432
432
|
);
|
|
433
433
|
});
|
|
434
434
|
const dispatcher = createDispatcher(createRegistry([nestedFeature]), {
|
|
@@ -466,7 +466,7 @@ describe("dispatcher.stream", () => {
|
|
|
466
466
|
throw new Error("close-boom");
|
|
467
467
|
}
|
|
468
468
|
},
|
|
469
|
-
{ access: { openToAll:
|
|
469
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
470
470
|
);
|
|
471
471
|
});
|
|
472
472
|
const dispatcher = createDispatcher(createRegistry([closeFailFeature]), {
|
|
@@ -500,7 +500,7 @@ describe("dispatcher.stream", () => {
|
|
|
500
500
|
yield { i: 0 };
|
|
501
501
|
yield { i: 1 };
|
|
502
502
|
},
|
|
503
|
-
{ access: { openToAll:
|
|
503
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
504
504
|
);
|
|
505
505
|
});
|
|
506
506
|
const dispatcher = createDispatcher(createRegistry([feature]), {
|
|
@@ -536,7 +536,7 @@ describe("dispatcher.stream", () => {
|
|
|
536
536
|
yield { i: 1 };
|
|
537
537
|
yield { i: 2 };
|
|
538
538
|
},
|
|
539
|
-
{ access: { openToAll:
|
|
539
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
540
540
|
);
|
|
541
541
|
});
|
|
542
542
|
const dispatcher = createDispatcher(createRegistry([feature]), {
|
|
@@ -571,7 +571,7 @@ describe("dispatcher.query postQuery hooks", () => {
|
|
|
571
571
|
// pass on entity-existence makes such a hook register silently + never run.
|
|
572
572
|
const feature = defineFeature("dash", (r) => {
|
|
573
573
|
r.queryHandler("dashboard", z.object({}), async () => ({ count: 1 }), {
|
|
574
|
-
access: { openToAll:
|
|
574
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
575
575
|
});
|
|
576
576
|
r.hook("postQuery", "dashboard", async ({ entityName, rows }) => {
|
|
577
577
|
expect(entityName).toBeUndefined();
|
|
@@ -590,7 +590,7 @@ describe("dispatcher.query postQuery hooks", () => {
|
|
|
590
590
|
// [...null]). The hook here returns the row unchanged so the shape survives.
|
|
591
591
|
const feature = defineFeature("nullrows", (r) => {
|
|
592
592
|
r.queryHandler("dashboard", z.object({}), async () => ({ rows: null, nextCursor: null }), {
|
|
593
|
-
access: { openToAll:
|
|
593
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
594
594
|
});
|
|
595
595
|
r.hook("postQuery", "dashboard", async ({ rows }) => ({ rows }));
|
|
596
596
|
});
|
|
@@ -603,7 +603,7 @@ describe("dispatcher.query postQuery hooks", () => {
|
|
|
603
603
|
test("single-object postQuery hook returning ≠1 row throws", async () => {
|
|
604
604
|
const feature = defineFeature("multi", (r) => {
|
|
605
605
|
r.queryHandler("dashboard", z.object({}), async () => ({ count: 1 }), {
|
|
606
|
-
access: { openToAll:
|
|
606
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
607
607
|
});
|
|
608
608
|
r.hook("postQuery", "dashboard", async ({ rows }) => ({ rows: [...rows, ...rows] }));
|
|
609
609
|
});
|
|
@@ -708,7 +708,7 @@ describe("dispatcher feature-gate", () => {
|
|
|
708
708
|
}),
|
|
709
709
|
);
|
|
710
710
|
r.queryHandler("widget:list", z.object({}).passthrough(), async () => ({ items: [] }), {
|
|
711
|
-
access: { openToAll:
|
|
711
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
712
712
|
});
|
|
713
713
|
r.writeHandler(
|
|
714
714
|
"widget:create",
|
|
@@ -728,7 +728,7 @@ describe("dispatcher feature-gate", () => {
|
|
|
728
728
|
i++;
|
|
729
729
|
}
|
|
730
730
|
},
|
|
731
|
-
{ access: { openToAll:
|
|
731
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
732
732
|
);
|
|
733
733
|
});
|
|
734
734
|
}
|
|
@@ -900,7 +900,7 @@ describe("dispatcher feature-gate", () => {
|
|
|
900
900
|
"check",
|
|
901
901
|
z.object({}).passthrough(),
|
|
902
902
|
async (_event, ctx) => ({ enabled: await ctx.hasFeature("toggled") }),
|
|
903
|
-
{ access: { openToAll:
|
|
903
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
904
904
|
);
|
|
905
905
|
});
|
|
906
906
|
const registry = createRegistry([toggled(), probe]);
|
|
@@ -940,7 +940,7 @@ describe("dispatcher feature-gate", () => {
|
|
|
940
940
|
"check",
|
|
941
941
|
z.object({}).passthrough(),
|
|
942
942
|
async (_event, ctx) => ({ enabled: await ctx.hasFeature("premium-companion") }),
|
|
943
|
-
{ access: { openToAll:
|
|
943
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
944
944
|
);
|
|
945
945
|
});
|
|
946
946
|
const registry = createRegistry([probe]);
|
|
@@ -1027,7 +1027,7 @@ describe("dispatcher context.geoTzProvider (680/1)", () => {
|
|
|
1027
1027
|
longitude: query.payload.longitude,
|
|
1028
1028
|
}),
|
|
1029
1029
|
}),
|
|
1030
|
-
{ access: { openToAll:
|
|
1030
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
1031
1031
|
);
|
|
1032
1032
|
});
|
|
1033
1033
|
const registry = createRegistry([geoFeature]);
|
|
@@ -24,7 +24,7 @@ function makeRegistry(hooks?: { preSave?: PreSaveHookFn[]; postSave?: PostSaveHo
|
|
|
24
24
|
);
|
|
25
25
|
// Dummy handler so hook targets resolve (boot validation requires it)
|
|
26
26
|
r.writeHandler("user", z.object({}), async () => ({ isSuccess: true as const, data: null }), {
|
|
27
|
-
access: { openToAll:
|
|
27
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
28
28
|
});
|
|
29
29
|
if (hooks?.preSave) {
|
|
30
30
|
for (const h of hooks.preSave) r.hook("preSave", "user", h);
|
|
@@ -296,7 +296,7 @@ describe("runPostSave phase routing", () => {
|
|
|
296
296
|
const feature = defineFeature("phases", (r) => {
|
|
297
297
|
r.entity("user", createEntity({ table: "Users", fields: {} }));
|
|
298
298
|
r.writeHandler("user", z.object({}), async () => ({ isSuccess: true, data: null }), {
|
|
299
|
-
access: { openToAll:
|
|
299
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
300
300
|
});
|
|
301
301
|
r.hook(
|
|
302
302
|
"postSave",
|
|
@@ -325,7 +325,7 @@ describe("runPostSave phase routing", () => {
|
|
|
325
325
|
const feature = defineFeature("phases", (r) => {
|
|
326
326
|
r.entity("user", createEntity({ table: "Users", fields: {} }));
|
|
327
327
|
r.writeHandler("user", z.object({}), async () => ({ isSuccess: true, data: null }), {
|
|
328
|
-
access: { openToAll:
|
|
328
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
329
329
|
});
|
|
330
330
|
r.hook(
|
|
331
331
|
"postSave",
|
|
@@ -351,7 +351,7 @@ describe("runPostSave phase routing", () => {
|
|
|
351
351
|
const feature = defineFeature("phases", (r) => {
|
|
352
352
|
r.entity("user", createEntity({ table: "Users", fields: {} }));
|
|
353
353
|
r.writeHandler("user", z.object({}), async () => ({ isSuccess: true, data: null }), {
|
|
354
|
-
access: { openToAll:
|
|
354
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
355
355
|
});
|
|
356
356
|
r.hook("postSave", "user", async () => {
|
|
357
357
|
throw new Error("afterCommit-boom");
|
|
@@ -378,7 +378,7 @@ describe("runPostSave phase routing", () => {
|
|
|
378
378
|
const feature = defineFeature("phases", (r) => {
|
|
379
379
|
r.entity("user", createEntity({ table: "Users", fields: {} }));
|
|
380
380
|
r.writeHandler("user", z.object({}), async () => ({ isSuccess: true, data: null }), {
|
|
381
|
-
access: { openToAll:
|
|
381
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
382
382
|
});
|
|
383
383
|
});
|
|
384
384
|
const registry = createRegistry([feature]);
|
|
@@ -439,7 +439,7 @@ describe("Sprint 8a: per-tenant entity-hook filter", () => {
|
|
|
439
439
|
"widget:create",
|
|
440
440
|
z.object({ name: z.string() }),
|
|
441
441
|
async () => ({ isSuccess: true as const, data: null }),
|
|
442
|
-
{ access: { openToAll:
|
|
442
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
443
443
|
);
|
|
444
444
|
});
|
|
445
445
|
|
|
@@ -570,7 +570,7 @@ describe("runPreDelete", () => {
|
|
|
570
570
|
}),
|
|
571
571
|
);
|
|
572
572
|
r.writeHandler("user", z.object({}), async () => ({ isSuccess: true as const, data: null }), {
|
|
573
|
-
access: { openToAll:
|
|
573
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
574
574
|
});
|
|
575
575
|
r.hook("preDelete", "user", async () => {
|
|
576
576
|
calls.push("handler");
|
|
@@ -606,7 +606,7 @@ describe("runPreDelete", () => {
|
|
|
606
606
|
}),
|
|
607
607
|
);
|
|
608
608
|
r.writeHandler("user", z.object({}), async () => ({ isSuccess: true as const, data: null }), {
|
|
609
|
-
access: { openToAll:
|
|
609
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
610
610
|
});
|
|
611
611
|
r.hook("preDelete", "user", async () => {
|
|
612
612
|
throw new Error("blocked-delete");
|
|
@@ -652,7 +652,7 @@ describe("runPostDelete", () => {
|
|
|
652
652
|
}),
|
|
653
653
|
);
|
|
654
654
|
r.writeHandler("user", z.object({}), async () => ({ isSuccess: true as const, data: null }), {
|
|
655
|
-
access: { openToAll:
|
|
655
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
656
656
|
});
|
|
657
657
|
r.hook("postDelete", "user", async () => {
|
|
658
658
|
calls.push("feature");
|
|
@@ -685,7 +685,7 @@ describe("runPostDelete", () => {
|
|
|
685
685
|
}),
|
|
686
686
|
);
|
|
687
687
|
r.writeHandler("user", z.object({}), async () => ({ isSuccess: true as const, data: null }), {
|
|
688
|
-
access: { openToAll:
|
|
688
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
689
689
|
});
|
|
690
690
|
r.hook(
|
|
691
691
|
"postDelete",
|
|
@@ -58,7 +58,7 @@ const postQueryFeature = defineFeature("postquerytest", (r) => {
|
|
|
58
58
|
],
|
|
59
59
|
nextCursor: null,
|
|
60
60
|
}),
|
|
61
|
-
{ access: { openToAll:
|
|
61
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
62
62
|
);
|
|
63
63
|
|
|
64
64
|
// Handler-keyed: fires only for widget:list
|
|
@@ -91,13 +91,13 @@ const duplicateRowHook: PostQueryHookFn = async ({ rows }) => ({ rows: [...rows,
|
|
|
91
91
|
const singleObjectFeature = defineFeature("singleobjtest", (r) => {
|
|
92
92
|
const gadget = r.entity("gadget", gadgetEntity);
|
|
93
93
|
r.queryHandler("gadget:get", z.object({}), async () => ({ id: "g1", name: "Gadget" }), {
|
|
94
|
-
access: { openToAll:
|
|
94
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
95
95
|
});
|
|
96
96
|
r.hook("postQuery", { allOf: gadget }, dropRowHook);
|
|
97
97
|
|
|
98
98
|
const gizmo = r.entity("gizmo", gizmoEntity);
|
|
99
99
|
r.queryHandler("gizmo:get", z.object({}), async () => ({ id: "z1", name: "Gizmo" }), {
|
|
100
|
-
access: { openToAll:
|
|
100
|
+
access: { openToAll: { reason: "test handler callable by any signed-in test user" } },
|
|
101
101
|
});
|
|
102
102
|
r.hook("postQuery", { allOf: gizmo }, duplicateRowHook);
|
|
103
103
|
});
|
|
@@ -92,7 +92,7 @@ const qpFeature = defineFeature("qp", (r) => {
|
|
|
92
92
|
"widget:list-tenant",
|
|
93
93
|
z.object({}),
|
|
94
94
|
async (_query, ctx) => ctx.queryProjection("qp:projection:widget-count-tenant"),
|
|
95
|
-
{ access: { openToAll:
|
|
95
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
96
96
|
);
|
|
97
97
|
|
|
98
98
|
r.queryHandler(
|
|
@@ -102,14 +102,14 @@ const qpFeature = defineFeature("qp", (r) => {
|
|
|
102
102
|
ctx.queryProjection("qp:projection:widget-audit", {
|
|
103
103
|
unsafeAllTenants: query.payload.unsafeAllTenants ?? false,
|
|
104
104
|
}),
|
|
105
|
-
{ access: { openToAll:
|
|
105
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
106
106
|
);
|
|
107
107
|
|
|
108
108
|
r.queryHandler(
|
|
109
109
|
"widget:list-ghost",
|
|
110
110
|
z.object({}),
|
|
111
111
|
async (_query, ctx) => ctx.queryProjection("qp:projection:does-not-exist"),
|
|
112
|
-
{ access: { openToAll:
|
|
112
|
+
{ access: { openToAll: { reason: "test handler callable by any signed-in test user" } } },
|
|
113
113
|
);
|
|
114
114
|
});
|
|
115
115
|
|