@cosmicdrift/kumiko-bundled-features 0.15.0 → 0.16.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-bundled-features",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "description": "Built-in features — tenant, user, auth, delivery. The stuff you'd rewrite anyway, already typed.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -0,0 +1,19 @@
1
+ import type { ComplianceProfileOverride } from "@cosmicdrift/kumiko-framework/compliance";
2
+ import { parseJsonSafe } from "@cosmicdrift/kumiko-framework/utils";
3
+
4
+ export function parseComplianceProfileOverride(
5
+ raw: string | null,
6
+ tenantId: string,
7
+ callerLabel: string,
8
+ ): ComplianceProfileOverride | undefined {
9
+ if (!raw || raw.trim() === "") return undefined;
10
+ const parsed = parseJsonSafe<ComplianceProfileOverride | null>(raw, null);
11
+ if (parsed === null) {
12
+ // biome-ignore lint/suspicious/noConsole: operator visibility for DB-corruption edge-case
13
+ console.warn(
14
+ `[${callerLabel}] tenant ${tenantId}: stored override is not valid JSON, ignoring.`,
15
+ );
16
+ return undefined;
17
+ }
18
+ return parsed;
19
+ }
@@ -1,12 +1,12 @@
1
1
  import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
2
2
  import {
3
3
  type ComplianceProfileKey,
4
- type ComplianceProfileOverride,
5
4
  type EffectiveComplianceProfile,
6
5
  resolveComplianceProfile,
7
6
  } from "@cosmicdrift/kumiko-framework/compliance";
8
7
  import { defineQueryHandler } from "@cosmicdrift/kumiko-framework/engine";
9
8
  import { z } from "zod";
9
+ import { parseComplianceProfileOverride } from "../_internal/parse-override";
10
10
  import { tenantComplianceProfileTable } from "../schema/profile-selection";
11
11
 
12
12
  // Liefert das effektive Compliance-Profile fuer den aktuellen Tenant.
@@ -29,33 +29,14 @@ export const forTenantQuery = defineQueryHandler({
29
29
  return resolveComplianceProfile({});
30
30
  }
31
31
 
32
- const override = parseOverride(row.override, query.user.tenantId);
32
+ const override = parseComplianceProfileOverride(
33
+ row.override,
34
+ query.user.tenantId,
35
+ "compliance-profiles:for-tenant",
36
+ );
33
37
  return resolveComplianceProfile({
34
38
  selection: row.profileKey as ComplianceProfileKey, // @cast-boundary engine-payload
35
39
  override,
36
40
  });
37
41
  },
38
42
  });
39
-
40
- function parseOverride(
41
- raw: string | null,
42
- tenantId: string,
43
- ): ComplianceProfileOverride | undefined {
44
- if (!raw || raw.trim() === "") return undefined;
45
- try {
46
- const parsed: unknown = JSON.parse(raw);
47
- return parsed as ComplianceProfileOverride; // @cast-boundary engine-payload
48
- } catch (e: unknown) {
49
- const reason = e instanceof Error ? e.message : String(e);
50
- // Defensiv: ungültiges JSON wird als "kein Override" behandelt. Der
51
- // set-profile-Handler validiert Zod das Override schon — invalides
52
- // JSON in der DB ist also nur möglich bei manueller DB-Manipulation
53
- // oder Migration-Bug. Resolver-Caller darf trotzdem nicht crashen.
54
- // Operator-Sichtbarkeit via console.warn — Telemetry-Hook spaeter.
55
- // biome-ignore lint/suspicious/noConsole: operator visibility for DB-corruption edge-case
56
- console.warn(
57
- `[compliance-profiles:for-tenant] tenant ${tenantId}: stored override is not valid JSON, falling back to base profile. Reason: ${reason}`,
58
- );
59
- return undefined;
60
- }
61
- }
@@ -11,12 +11,12 @@
11
11
  import { fetchOne } from "@cosmicdrift/kumiko-framework/bun-db";
12
12
  import {
13
13
  type ComplianceProfileKey,
14
- type ComplianceProfileOverride,
15
14
  type EffectiveComplianceProfile,
16
15
  resolveComplianceProfile,
17
16
  } from "@cosmicdrift/kumiko-framework/compliance";
18
17
  import type { DbRunner } from "@cosmicdrift/kumiko-framework/db";
19
18
  import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
19
+ import { parseComplianceProfileOverride } from "./_internal/parse-override";
20
20
  import { tenantComplianceProfileTable } from "./schema/profile-selection";
21
21
 
22
22
  export interface ResolveProfileForTenantArgs {
@@ -35,27 +35,13 @@ export async function resolveProfileForTenant(
35
35
  return resolveComplianceProfile({});
36
36
  }
37
37
 
38
- const override = parseOverride(row.override, args.tenantId);
38
+ const override = parseComplianceProfileOverride(
39
+ row.override,
40
+ args.tenantId,
41
+ "compliance-profiles:resolve-for-tenant",
42
+ );
39
43
  return resolveComplianceProfile({
40
44
  selection: row.profileKey as ComplianceProfileKey, // @cast-boundary engine-payload
41
45
  override,
42
46
  });
43
47
  }
44
-
45
- function parseOverride(
46
- raw: string | null,
47
- tenantId: string,
48
- ): ComplianceProfileOverride | undefined {
49
- if (!raw || raw.trim() === "") return undefined;
50
- try {
51
- const parsed: unknown = JSON.parse(raw);
52
- return parsed as ComplianceProfileOverride; // @cast-boundary engine-payload
53
- } catch (e: unknown) {
54
- const reason = e instanceof Error ? e.message : String(e);
55
- // biome-ignore lint/suspicious/noConsole: operator visibility for DB-corruption edge-case
56
- console.warn(
57
- `[compliance-profiles:resolve-for-tenant] tenant ${tenantId}: stored override is not valid JSON, ignoring. Reason: ${reason}`,
58
- );
59
- return undefined;
60
- }
61
- }
@@ -6,12 +6,19 @@ import { deliveryAttemptSchema } from "./events";
6
6
  import { logQuery } from "./handlers/log.query";
7
7
  import { preferencesQuery } from "./handlers/preferences.query";
8
8
  import { setPreferenceWrite } from "./handlers/set-preference.write";
9
- import { deliveryAttemptsTable, notificationPreferenceEntity } from "./tables";
9
+ import {
10
+ deliveryAttemptsTable,
11
+ deliveryAttemptsTableMeta,
12
+ notificationPreferenceEntity,
13
+ } from "./tables";
10
14
 
11
15
  export function createDeliveryFeature(): FeatureDefinition {
12
16
  return defineFeature("delivery", (r) => {
13
17
  r.systemScope();
14
18
  r.entity("notification-preference", notificationPreferenceEntity);
19
+ r.unmanagedTable(deliveryAttemptsTableMeta, {
20
+ reason: "read_side.delivery_attempt_log",
21
+ });
15
22
 
16
23
  // Events-only projection source: "deliveryAttempt" is the aggregate-
17
24
  // type on the events-table, but there's no r.entity for it — each
@@ -19,11 +19,14 @@ import {
19
19
  JOB_RUN_FAILED_EVENT,
20
20
  JOB_RUN_STARTED_EVENT,
21
21
  } from "./job-run-logger";
22
- import { jobRunLogsTable, jobRunsTable } from "./job-run-table";
22
+ import { jobRunLogsTable, jobRunLogsTableMeta, jobRunsTable } from "./job-run-table";
23
23
 
24
24
  export function createJobsFeature(): FeatureDefinition {
25
25
  return defineFeature("jobs", (r) => {
26
26
  r.systemScope();
27
+ r.unmanagedTable(jobRunLogsTableMeta, {
28
+ reason: "read_side.job_run_logs",
29
+ });
27
30
  // Events-only aggregate: "jobRun" has no r.entity registration, because
28
31
  // the entire lifecycle is driven by BullMQ-callback → r.defineEvent
29
32
  // (no executor, no CRUD). The boot-validator accepts the two