@kernhq/module-inventory 0.1.2 → 0.2.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.
Files changed (103) hide show
  1. package/README.md +55 -9
  2. package/dist/contract/capabilities.d.ts +49 -0
  3. package/dist/contract/capabilities.d.ts.map +1 -0
  4. package/dist/contract/capabilities.js +52 -0
  5. package/dist/contract/capabilities.js.map +1 -0
  6. package/dist/contract/events.d.ts +33 -0
  7. package/dist/contract/events.d.ts.map +1 -0
  8. package/dist/contract/events.js +22 -0
  9. package/dist/contract/events.js.map +1 -0
  10. package/dist/contract/index.d.ts +15 -0
  11. package/dist/contract/index.d.ts.map +1 -0
  12. package/dist/contract/index.js +15 -0
  13. package/dist/contract/index.js.map +1 -0
  14. package/dist/contract/models.d.ts +146 -0
  15. package/dist/contract/models.d.ts.map +1 -0
  16. package/dist/contract/models.js +107 -0
  17. package/dist/contract/models.js.map +1 -0
  18. package/dist/contract/permissions.d.ts +22 -0
  19. package/dist/contract/permissions.d.ts.map +1 -0
  20. package/dist/contract/permissions.js +26 -0
  21. package/dist/contract/permissions.js.map +1 -0
  22. package/dist/{contract.d.ts → contract/router.d.ts} +24 -85
  23. package/dist/contract/router.d.ts.map +1 -0
  24. package/dist/contract/router.js +42 -0
  25. package/dist/contract/router.js.map +1 -0
  26. package/dist/contract/settings.d.ts +18 -0
  27. package/dist/contract/settings.d.ts.map +1 -0
  28. package/dist/contract/settings.js +29 -0
  29. package/dist/contract/settings.js.map +1 -0
  30. package/dist/server/index.d.ts +4 -1
  31. package/dist/server/index.d.ts.map +1 -1
  32. package/dist/server/index.js +9 -13
  33. package/dist/server/index.js.map +1 -1
  34. package/dist/server/{_impl.d.ts → router.d.ts} +33 -8
  35. package/dist/server/{_impl.d.ts.map → router.d.ts.map} +1 -1
  36. package/dist/server/router.js +83 -0
  37. package/dist/server/router.js.map +1 -0
  38. package/dist/server/schema.d.ts +25 -11
  39. package/dist/server/schema.d.ts.map +1 -1
  40. package/dist/server/schema.js +28 -10
  41. package/dist/server/schema.js.map +1 -1
  42. package/dist/server/services/assets.d.ts +73 -0
  43. package/dist/server/services/assets.d.ts.map +1 -0
  44. package/dist/server/services/assets.js +261 -0
  45. package/dist/server/services/assets.js.map +1 -0
  46. package/dist/server/services/index.d.ts +10 -0
  47. package/dist/server/services/index.d.ts.map +1 -0
  48. package/dist/server/services/index.js +15 -0
  49. package/dist/server/services/index.js.map +1 -0
  50. package/dist/server/services/notify.d.ts +63 -0
  51. package/dist/server/services/notify.d.ts.map +1 -0
  52. package/dist/server/services/notify.js +105 -0
  53. package/dist/server/services/notify.js.map +1 -0
  54. package/migrations/0000_init.sql +12 -3
  55. package/migrations/0001_rls.sql +24 -0
  56. package/migrations/meta/0000_snapshot.json +40 -13
  57. package/migrations/meta/_journal.json +2 -2
  58. package/package.json +5 -4
  59. package/src/client/api.ts +1 -1
  60. package/src/client/components/AssetFormDialog.svelte +130 -47
  61. package/src/client/i18n.ts +11 -166
  62. package/src/client/index.ts +8 -1
  63. package/src/client/messages.test.ts +169 -0
  64. package/src/client/messages.ts +399 -0
  65. package/src/client/mock.test.ts +161 -0
  66. package/src/client/mock.ts +267 -45
  67. package/src/client/module.ts +22 -2
  68. package/src/client/pages/AssetsPage.svelte +358 -137
  69. package/src/client/permissions.ts +1 -1
  70. package/src/client/price.test.ts +106 -0
  71. package/src/client/price.ts +135 -0
  72. package/src/client/query.test.ts +58 -0
  73. package/src/client/query.ts +15 -2
  74. package/src/client/settings/GeneralSettings.svelte +0 -0
  75. package/src/client/settings/core-api.ts +32 -0
  76. package/src/client/widgets/OverviewWidget.svelte +16 -3
  77. package/src/contract/capabilities.ts +55 -0
  78. package/src/contract/events.ts +34 -0
  79. package/src/contract/index.ts +15 -0
  80. package/src/contract/models.ts +123 -0
  81. package/src/contract/permissions.ts +26 -0
  82. package/src/contract/router.ts +46 -0
  83. package/src/contract/settings.ts +30 -0
  84. package/src/module.test.ts +140 -7
  85. package/src/server/index.ts +16 -13
  86. package/src/server/inventory.int.test.ts +819 -0
  87. package/src/server/migrations.test.ts +138 -0
  88. package/src/server/router.ts +118 -0
  89. package/src/server/schema.ts +27 -10
  90. package/src/server/services/assets.ts +368 -0
  91. package/src/server/services/index.ts +23 -0
  92. package/src/server/services/notify.ts +151 -0
  93. package/tsconfig.base.json +22 -0
  94. package/tsconfig.client.json +1 -1
  95. package/tsconfig.json +1 -1
  96. package/vitest.config.ts +18 -3
  97. package/dist/contract.d.ts.map +0 -1
  98. package/dist/contract.js +0 -119
  99. package/dist/contract.js.map +0 -1
  100. package/dist/server/_impl.js +0 -204
  101. package/dist/server/_impl.js.map +0 -1
  102. package/src/contract.ts +0 -143
  103. package/src/server/_impl.ts +0 -275
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../../src/server/services/assets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Kernel } from '@kernhq/kernel';
2
+ import { AssetService } from './assets.js';
3
+ import { NotifyService } from './notify.js';
4
+ export interface InventoryServices {
5
+ notify: NotifyService;
6
+ assets: AssetService;
7
+ }
8
+ /** One service graph per kernel instance; the router, jobs and procedures all share it. */
9
+ export declare function inventoryServices(kernel: Kernel): InventoryServices;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/services/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE3C,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,aAAa,CAAA;IACrB,MAAM,EAAE,YAAY,CAAA;CACrB;AAID,2FAA2F;AAC3F,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAUnE"}
@@ -0,0 +1,15 @@
1
+ import { AssetService } from './assets.js';
2
+ import { NotifyService } from './notify.js';
3
+ const cache = new WeakMap();
4
+ /** One service graph per kernel instance; the router, jobs and procedures all share it. */
5
+ export function inventoryServices(kernel) {
6
+ const existing = cache.get(kernel);
7
+ if (existing)
8
+ return existing;
9
+ const notify = new NotifyService(kernel);
10
+ const assets = new AssetService(kernel, notify);
11
+ const services = { notify, assets };
12
+ cache.set(kernel, services);
13
+ return services;
14
+ }
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/server/services/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAO3C,MAAM,KAAK,GAAG,IAAI,OAAO,EAA6B,CAAA;AAEtD,2FAA2F;AAC3F,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IAClC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAE7B,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAA;IACxC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAE/C,MAAM,QAAQ,GAAsB,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;IACtD,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAC3B,OAAO,QAAQ,CAAA;AACjB,CAAC"}
@@ -0,0 +1,63 @@
1
+ import type { core, EntityChange, ObjectRef } from '@kernhq/contracts';
2
+ import { type Kernel, type Tx } from '@kernhq/kernel';
3
+ export interface HistoryInput {
4
+ workspaceId: string;
5
+ assetId: string;
6
+ actorId: string | null;
7
+ action: string;
8
+ changes?: Array<{
9
+ field: string;
10
+ from: unknown;
11
+ to: unknown;
12
+ }>;
13
+ data?: Record<string, unknown>;
14
+ }
15
+ export interface NotifyInput {
16
+ workspaceId: string;
17
+ userIds: Iterable<string>;
18
+ type: string;
19
+ title: string;
20
+ body?: string | null;
21
+ object?: ObjectRef | null;
22
+ url?: string | null;
23
+ data?: Record<string, unknown>;
24
+ groupKey?: string | null;
25
+ actorId?: string | null;
26
+ /** never notify the person who caused the change */
27
+ exclude?: Iterable<string | null | undefined>;
28
+ }
29
+ /**
30
+ * Side effects that leave the module: activity, notifications, realtime and the search index.
31
+ *
32
+ * All of them are best-effort. An inventory mutation must not fail because the core service is
33
+ * briefly unavailable, so every cross-module call is swallowed and logged — the local
34
+ * `asset_history` row is written inside the caller's transaction and remains the authoritative
35
+ * record of what happened.
36
+ */
37
+ export declare class NotifyService {
38
+ private readonly kernel;
39
+ constructor(kernel: Kernel);
40
+ private best;
41
+ /**
42
+ * Append to the asset's own history, inside the caller's transaction.
43
+ *
44
+ * This row is the authoritative record and belongs in the transaction it describes — if the write
45
+ * rolls back, so does its history. The mirror of it in core's activity feed is `activity()`, and
46
+ * it deliberately does **not** happen here: it used to, fired off with `void` while the
47
+ * transaction was still open, so a rollback left the workspace's feed showing an event for an id
48
+ * that never existed. The caller flushes it after the commit, beside the event and the realtime
49
+ * change, which is what everything else in this module already does.
50
+ */
51
+ history(tx: Tx, input: HistoryInput): Promise<void>;
52
+ /** The workspace-wide activity feed's copy. Best-effort, and only ever after the commit. */
53
+ activity(input: HistoryInput): Promise<void>;
54
+ notify(input: NotifyInput): Promise<void>;
55
+ /** Realtime cache invalidation for connected clients. */
56
+ change(workspaceId: string, entity: string, id: string, op: EntityChange['op'], opts?: {
57
+ patch?: Record<string, unknown>;
58
+ scope?: Record<string, string>;
59
+ }): Promise<void>;
60
+ index(documents: core.SearchDocument[]): Promise<void>;
61
+ unindex(workspaceId: string, type: string, ids: string[]): Promise<void>;
62
+ }
63
+ //# sourceMappingURL=notify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../../src/server/services/notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAE,KAAK,MAAM,EAAE,KAAK,EAAE,EAAU,MAAM,gBAAgB,CAAA;AAI7D,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IACzB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,oDAAoD;IACpD,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;CAC9C;AAED;;;;;;;GAOG;AACH,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,MAAM;YAE7B,IAAI;IAYlB;;;;;;;;;OASG;IACG,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAYzD,4FAA4F;IACtF,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5C,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB/C,yDAAyD;IACnD,MAAM,CACV,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,EACtB,IAAI,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAO,GAC7E,OAAO,CAAC,IAAI,CAAC;IAgBV,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtD,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAQ/E"}
@@ -0,0 +1,105 @@
1
+ import { uuidv7 } from '@kernhq/kernel';
2
+ import { MODULE_ID } from '../../contract/models.js';
3
+ import { assetHistory } from '../schema.js';
4
+ /**
5
+ * Side effects that leave the module: activity, notifications, realtime and the search index.
6
+ *
7
+ * All of them are best-effort. An inventory mutation must not fail because the core service is
8
+ * briefly unavailable, so every cross-module call is swallowed and logged — the local
9
+ * `asset_history` row is written inside the caller's transaction and remains the authoritative
10
+ * record of what happened.
11
+ */
12
+ export class NotifyService {
13
+ kernel;
14
+ constructor(kernel) {
15
+ this.kernel = kernel;
16
+ }
17
+ async best(what, fn) {
18
+ try {
19
+ return await fn();
20
+ }
21
+ catch (err) {
22
+ this.kernel.log.warn({ err: err instanceof Error ? err.message : err, what }, 'inventory side effect failed');
23
+ return null;
24
+ }
25
+ }
26
+ /**
27
+ * Append to the asset's own history, inside the caller's transaction.
28
+ *
29
+ * This row is the authoritative record and belongs in the transaction it describes — if the write
30
+ * rolls back, so does its history. The mirror of it in core's activity feed is `activity()`, and
31
+ * it deliberately does **not** happen here: it used to, fired off with `void` while the
32
+ * transaction was still open, so a rollback left the workspace's feed showing an event for an id
33
+ * that never existed. The caller flushes it after the commit, beside the event and the realtime
34
+ * change, which is what everything else in this module already does.
35
+ */
36
+ async history(tx, input) {
37
+ await tx.insert(assetHistory).values({
38
+ id: uuidv7(),
39
+ workspaceId: input.workspaceId,
40
+ assetId: input.assetId,
41
+ actorId: input.actorId,
42
+ action: input.action,
43
+ changes: input.changes ?? [],
44
+ data: input.data ?? {},
45
+ });
46
+ }
47
+ /** The workspace-wide activity feed's copy. Best-effort, and only ever after the commit. */
48
+ async activity(input) {
49
+ await this.best('activity.record', () => this.kernel.call('core.activity.record', {
50
+ workspaceId: input.workspaceId,
51
+ module: MODULE_ID,
52
+ object: { module: MODULE_ID, type: 'asset', id: input.assetId },
53
+ action: input.action,
54
+ actorId: input.actorId,
55
+ changes: input.changes ?? [],
56
+ data: input.data ?? {},
57
+ }));
58
+ }
59
+ async notify(input) {
60
+ const excluded = new Set([...(input.exclude ?? [])].filter(Boolean));
61
+ const targets = [...new Set(input.userIds)].filter((id) => id && !excluded.has(id));
62
+ if (!targets.length)
63
+ return;
64
+ await Promise.all(targets.map((userId) => this.best('notifications.create', () => this.kernel.call('core.notifications.create', {
65
+ userId,
66
+ workspaceId: input.workspaceId,
67
+ module: MODULE_ID,
68
+ type: input.type,
69
+ title: input.title,
70
+ body: input.body ?? null,
71
+ object: input.object ?? null,
72
+ url: input.url ?? null,
73
+ data: input.data ?? {},
74
+ groupKey: input.groupKey ?? null,
75
+ actorId: input.actorId ?? null,
76
+ }))));
77
+ }
78
+ /** Realtime cache invalidation for connected clients. */
79
+ async change(workspaceId, entity, id, op, opts = {}) {
80
+ await this.best('realtime.change', () => this.kernel.realtime.change(workspaceId, {
81
+ module: MODULE_ID,
82
+ entity,
83
+ id,
84
+ op,
85
+ ...(opts.patch ? { patch: opts.patch } : {}),
86
+ ...(opts.scope ? { scope: opts.scope } : {}),
87
+ }));
88
+ }
89
+ // Nothing calls `index`/`unindex` yet: `objectTypes` came off the module definition until there
90
+ // is a resolver and an indexer to stand behind it. They are kept as they are, copied from
91
+ // tracker, and are wired up by the change that declares the object type again.
92
+ async index(documents) {
93
+ if (!documents.length)
94
+ return;
95
+ await this.best('search.index', () => this.kernel.call('core.search.index', { documents }));
96
+ }
97
+ async unindex(workspaceId, type, ids) {
98
+ if (!ids.length)
99
+ return;
100
+ await this.best('search.remove', () => this.kernel.call('core.search.remove', {
101
+ refs: ids.map((id) => ({ workspaceId, object: { module: MODULE_ID, type, id } })),
102
+ }));
103
+ }
104
+ }
105
+ //# sourceMappingURL=notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../../src/server/services/notify.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,15 @@
1
1
  -- `create schema if not exists` matters: the kernel creates `mod_inventory` before running these, so
2
- -- the bare form fails on boot.
2
+ -- the bare form fails on boot. Every table and index is guarded the same way, so an interrupted
3
+ -- first boot can be retried rather than needing the schema dropped by hand.
4
+ --
5
+ -- `btree_gist` is what lets an exclusion constraint mix `uuid with =` and `tstzrange with &&`, which
6
+ -- is how `0001_rls.sql` makes two open custody periods for one asset impossible. Without it that
7
+ -- constraint fails with "data type uuid has no default operator class for access method gist" —
8
+ -- during the module's own migration, so the *service does not start*. Core creates four extensions
9
+ -- and this is not one of them; HR declares its own for the same reason.
10
+ CREATE EXTENSION IF NOT EXISTS btree_gist;--> statement-breakpoint
3
11
  CREATE SCHEMA IF NOT EXISTS "mod_inventory";
4
12
  --> statement-breakpoint
5
- CREATE TYPE "public"."asset_status" AS ENUM('in_stock', 'assigned', 'under_repair', 'retired');--> statement-breakpoint
6
13
  CREATE TABLE IF NOT EXISTS "mod_inventory"."asset_history" (
7
14
  "id" uuid PRIMARY KEY DEFAULT uuidv7() NOT NULL,
8
15
  "workspace_id" uuid NOT NULL,
@@ -21,7 +28,7 @@ CREATE TABLE IF NOT EXISTS "mod_inventory"."assets" (
21
28
  "name" text NOT NULL,
22
29
  "description" text DEFAULT '' NOT NULL,
23
30
  "category_id" uuid,
24
- "status" "asset_status" DEFAULT 'in_stock' NOT NULL,
31
+ "status" text DEFAULT 'in_stock' NOT NULL,
25
32
  "custodian_user_id" uuid,
26
33
  "custody_since" timestamp with time zone,
27
34
  "serial_number" text,
@@ -32,6 +39,7 @@ CREATE TABLE IF NOT EXISTS "mod_inventory"."assets" (
32
39
  "currency" char(3),
33
40
  "warranty_until" date,
34
41
  "photo_file_id" uuid,
42
+ "custom" jsonb DEFAULT '{}'::jsonb NOT NULL,
35
43
  "created_at" timestamp with time zone DEFAULT now() NOT NULL,
36
44
  "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
37
45
  "archived_at" timestamp with time zone
@@ -118,6 +126,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS "inventory_assets_ws_code_uq" ON "mod_inventor
118
126
  CREATE INDEX IF NOT EXISTS "inventory_assets_ws_created_idx" ON "mod_inventory"."assets" USING btree ("workspace_id","created_at");--> statement-breakpoint
119
127
  CREATE INDEX IF NOT EXISTS "inventory_assets_ws_status_idx" ON "mod_inventory"."assets" USING btree ("workspace_id","status");--> statement-breakpoint
120
128
  CREATE INDEX IF NOT EXISTS "inventory_assets_ws_category_idx" ON "mod_inventory"."assets" USING btree ("workspace_id","category_id");--> statement-breakpoint
129
+ CREATE INDEX IF NOT EXISTS "inventory_assets_ws_custodian_idx" ON "mod_inventory"."assets" USING btree ("workspace_id","custodian_user_id") WHERE custodian_user_id is not null;--> statement-breakpoint
121
130
  CREATE INDEX IF NOT EXISTS "inventory_assets_ws_warranty_idx" ON "mod_inventory"."assets" USING btree ("workspace_id","warranty_until") WHERE warranty_until is not null;--> statement-breakpoint
122
131
  CREATE UNIQUE INDEX IF NOT EXISTS "inventory_attachments_asset_file_uq" ON "mod_inventory"."attachments" USING btree ("asset_id","file_id");--> statement-breakpoint
123
132
  CREATE INDEX IF NOT EXISTS "inventory_attachments_ws_asset_idx" ON "mod_inventory"."attachments" USING btree ("workspace_id","asset_id","created_at");--> statement-breakpoint
@@ -1,5 +1,13 @@
1
1
  -- Row-level security. Hand-written, because drizzle-kit does not generate it.
2
2
  --
3
+ -- **Every statement here is idempotent, and that is not decoration.** A module's migrations are the
4
+ -- first thing the kernel runs, so one that throws does not break its own module — it takes down the
5
+ -- whole host service, and `core` hosts five. `create policy` has no `if not exists`, so each is
6
+ -- preceded by an explicit drop; the same for the exclusion constraint. This file was replayed
7
+ -- against a schema that already had it (a regenerated journal is enough to cause that) and answered
8
+ -- `policy "categories_ws_isolation" for table "categories" already exists`, which stopped core
9
+ -- booting for everything, not only for inventory.
10
+ --
3
11
  -- This is the last line, not the first: the API already checks membership and permission. It exists
4
12
  -- for the query that skips them — a job, a report, a mistake — and for anyone who reaches the
5
13
  -- database another way. A tenant table without a policy is simply readable.
@@ -8,44 +16,58 @@
8
16
  -- block per table. Superusers bypass RLS, so a database owned by one will pass a test that proves
9
17
  -- nothing: run the application as a plain role.
10
18
 
19
+ alter table "mod_inventory"."counters" enable row level security;--> statement-breakpoint
20
+ alter table "mod_inventory"."counters" force row level security;--> statement-breakpoint
21
+ drop policy if exists "counters_ws_isolation" on "mod_inventory"."counters";--> statement-breakpoint
22
+ create policy "counters_ws_isolation" on "mod_inventory"."counters"
23
+ using (workspace_id::text = current_setting('app.workspace_id', true))
24
+ with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
25
+
11
26
  alter table "mod_inventory"."categories" enable row level security;--> statement-breakpoint
12
27
  alter table "mod_inventory"."categories" force row level security;--> statement-breakpoint
28
+ drop policy if exists "categories_ws_isolation" on "mod_inventory"."categories";--> statement-breakpoint
13
29
  create policy "categories_ws_isolation" on "mod_inventory"."categories"
14
30
  using (workspace_id::text = current_setting('app.workspace_id', true))
15
31
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
16
32
 
17
33
  alter table "mod_inventory"."assets" enable row level security;--> statement-breakpoint
18
34
  alter table "mod_inventory"."assets" force row level security;--> statement-breakpoint
35
+ drop policy if exists "assets_ws_isolation" on "mod_inventory"."assets";--> statement-breakpoint
19
36
  create policy "assets_ws_isolation" on "mod_inventory"."assets"
20
37
  using (workspace_id::text = current_setting('app.workspace_id', true))
21
38
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
22
39
 
23
40
  alter table "mod_inventory"."field_defs" enable row level security;--> statement-breakpoint
24
41
  alter table "mod_inventory"."field_defs" force row level security;--> statement-breakpoint
42
+ drop policy if exists "field_defs_ws_isolation" on "mod_inventory"."field_defs";--> statement-breakpoint
25
43
  create policy "field_defs_ws_isolation" on "mod_inventory"."field_defs"
26
44
  using (workspace_id::text = current_setting('app.workspace_id', true))
27
45
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
28
46
 
29
47
  alter table "mod_inventory"."custody_periods" enable row level security;--> statement-breakpoint
30
48
  alter table "mod_inventory"."custody_periods" force row level security;--> statement-breakpoint
49
+ drop policy if exists "custody_periods_ws_isolation" on "mod_inventory"."custody_periods";--> statement-breakpoint
31
50
  create policy "custody_periods_ws_isolation" on "mod_inventory"."custody_periods"
32
51
  using (workspace_id::text = current_setting('app.workspace_id', true))
33
52
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
34
53
 
35
54
  alter table "mod_inventory"."asset_history" enable row level security;--> statement-breakpoint
36
55
  alter table "mod_inventory"."asset_history" force row level security;--> statement-breakpoint
56
+ drop policy if exists "asset_history_ws_isolation" on "mod_inventory"."asset_history";--> statement-breakpoint
37
57
  create policy "asset_history_ws_isolation" on "mod_inventory"."asset_history"
38
58
  using (workspace_id::text = current_setting('app.workspace_id', true))
39
59
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
40
60
 
41
61
  alter table "mod_inventory"."repairs" enable row level security;--> statement-breakpoint
42
62
  alter table "mod_inventory"."repairs" force row level security;--> statement-breakpoint
63
+ drop policy if exists "repairs_ws_isolation" on "mod_inventory"."repairs";--> statement-breakpoint
43
64
  create policy "repairs_ws_isolation" on "mod_inventory"."repairs"
44
65
  using (workspace_id::text = current_setting('app.workspace_id', true))
45
66
  with check (workspace_id::text = current_setting('app.workspace_id', true));--> statement-breakpoint
46
67
 
47
68
  alter table "mod_inventory"."attachments" enable row level security;--> statement-breakpoint
48
69
  alter table "mod_inventory"."attachments" force row level security;--> statement-breakpoint
70
+ drop policy if exists "attachments_ws_isolation" on "mod_inventory"."attachments";--> statement-breakpoint
49
71
  create policy "attachments_ws_isolation" on "mod_inventory"."attachments"
50
72
  using (workspace_id::text = current_setting('app.workspace_id', true))
51
73
  with check (workspace_id::text = current_setting('app.workspace_id', true));
@@ -54,6 +76,8 @@ create policy "attachments_ws_isolation" on "mod_inventory"."attachments"
54
76
  -- is what makes two overlapping custody periods for one asset impossible at the database level —
55
77
  -- two concurrent transfers cannot both win. `effective_to` null means "still open", which tstzrange
56
78
  -- treats as unbounded, so an open period conflicts with everything that would follow it.
79
+ alter table "mod_inventory"."custody_periods"
80
+ drop constraint if exists "inventory_custody_no_overlap";--> statement-breakpoint
57
81
  alter table "mod_inventory"."custody_periods"
58
82
  add constraint "inventory_custody_no_overlap"
59
83
  exclude using gist (
@@ -1,5 +1,5 @@
1
1
  {
2
- "id": "50998845-5c27-429f-ba8d-b7beda4579b4",
2
+ "id": "33173d81-879e-409b-a7c7-d8f9977b9e6c",
3
3
  "prevId": "00000000-0000-0000-0000-000000000000",
4
4
  "version": "7",
5
5
  "dialect": "postgresql",
@@ -139,8 +139,7 @@
139
139
  },
140
140
  "status": {
141
141
  "name": "status",
142
- "type": "asset_status",
143
- "typeSchema": "public",
142
+ "type": "text",
144
143
  "primaryKey": false,
145
144
  "notNull": true,
146
145
  "default": "'in_stock'"
@@ -205,6 +204,13 @@
205
204
  "primaryKey": false,
206
205
  "notNull": false
207
206
  },
207
+ "custom": {
208
+ "name": "custom",
209
+ "type": "jsonb",
210
+ "primaryKey": false,
211
+ "notNull": true,
212
+ "default": "'{}'::jsonb"
213
+ },
208
214
  "created_at": {
209
215
  "name": "created_at",
210
216
  "type": "timestamp with time zone",
@@ -311,6 +317,28 @@
311
317
  "method": "btree",
312
318
  "with": {}
313
319
  },
320
+ "inventory_assets_ws_custodian_idx": {
321
+ "name": "inventory_assets_ws_custodian_idx",
322
+ "columns": [
323
+ {
324
+ "expression": "workspace_id",
325
+ "isExpression": false,
326
+ "asc": true,
327
+ "nulls": "last"
328
+ },
329
+ {
330
+ "expression": "custodian_user_id",
331
+ "isExpression": false,
332
+ "asc": true,
333
+ "nulls": "last"
334
+ }
335
+ ],
336
+ "isUnique": false,
337
+ "where": "custodian_user_id is not null",
338
+ "concurrently": false,
339
+ "method": "btree",
340
+ "with": {}
341
+ },
314
342
  "inventory_assets_ws_warranty_idx": {
315
343
  "name": "inventory_assets_ws_warranty_idx",
316
344
  "columns": [
@@ -568,13 +596,13 @@
568
596
  "workspace_id": {
569
597
  "name": "workspace_id",
570
598
  "type": "uuid",
571
- "primaryKey": true,
599
+ "primaryKey": false,
572
600
  "notNull": true
573
601
  },
574
602
  "key": {
575
603
  "name": "key",
576
604
  "type": "text",
577
- "primaryKey": true,
605
+ "primaryKey": false,
578
606
  "notNull": true
579
607
  },
580
608
  "value": {
@@ -586,7 +614,12 @@
586
614
  },
587
615
  "indexes": {},
588
616
  "foreignKeys": {},
589
- "compositePrimaryKeys": {},
617
+ "compositePrimaryKeys": {
618
+ "counters_workspace_id_key_pk": {
619
+ "name": "counters_workspace_id_key_pk",
620
+ "columns": ["workspace_id", "key"]
621
+ }
622
+ },
590
623
  "uniqueConstraints": {},
591
624
  "policies": {},
592
625
  "checkConstraints": {},
@@ -972,13 +1005,7 @@
972
1005
  "isRLSEnabled": false
973
1006
  }
974
1007
  },
975
- "enums": {
976
- "public.asset_status": {
977
- "name": "asset_status",
978
- "schema": "public",
979
- "values": ["in_stock", "assigned", "under_repair", "retired"]
980
- }
981
- },
1008
+ "enums": {},
982
1009
  "schemas": {
983
1010
  "mod_inventory": "mod_inventory"
984
1011
  },
@@ -5,14 +5,14 @@
5
5
  {
6
6
  "idx": 0,
7
7
  "version": "7",
8
- "when": 1787738327443,
8
+ "when": 1787759199523,
9
9
  "tag": "0000_init",
10
10
  "breakpoints": true
11
11
  },
12
12
  {
13
13
  "idx": 1,
14
14
  "version": "7",
15
- "when": 1787738328443,
15
+ "when": 1787759200523,
16
16
  "tag": "0001_rls",
17
17
  "breakpoints": true
18
18
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kernhq/module-inventory",
3
- "version": "0.1.2",
4
- "description": "Kern inventory module: the company's asset register — what it owns, who holds each item, purchase and warranty details, repairs, and a full history of every change",
3
+ "version": "0.2.0",
4
+ "description": "Kern inventory module: the company's asset register — what it owns, item by item, with asset tags, serial numbers, purchase and warranty details",
5
5
  "homepage": "https://github.com/KernAIO/module-inventory#readme",
6
6
  "license": "AGPL-3.0-only",
7
7
  "type": "module",
@@ -21,6 +21,7 @@
21
21
  "migrations",
22
22
  "src",
23
23
  "drizzle.config.ts",
24
+ "tsconfig.base.json",
24
25
  "tsconfig.json",
25
26
  "tsconfig.client.json",
26
27
  "vitest.config.ts",
@@ -63,7 +64,7 @@
63
64
  "@kernhq/contracts": "^0.7.0",
64
65
  "@kernhq/kernel": "^0.7.0",
65
66
  "@kernhq/tsconfig": "^0.1.0",
66
- "@kernhq/ui": "^0.10.0",
67
+ "@kernhq/ui": "^0.12.0",
67
68
  "@tanstack/svelte-query": "^6.1.0",
68
69
  "@types/node": "^24.0.0",
69
70
  "@types/pg": "^8.15.0",
@@ -77,7 +78,7 @@
77
78
  "peerDependencies": {
78
79
  "@kernhq/contracts": "^0.7.0",
79
80
  "@kernhq/kernel": "^0.7.0",
80
- "@kernhq/ui": "^0.10.0",
81
+ "@kernhq/ui": "^0.12.0",
81
82
  "@tanstack/svelte-query": "^6.1.0",
82
83
  "svelte": "^5.46.0"
83
84
  },
package/src/client/api.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createModuleClient, type KernClientOptions } from '@kernhq/sdk'
2
2
  import type { ContractRouterClient } from '@orpc/contract'
3
- import type { InventoryContract } from '../contract.js'
3
+ import type { InventoryContract } from '../contract/index.js'
4
4
 
5
5
  /** The typed client, derived from the contract — no hand-written method list to drift. */
6
6
  export type InventoryApi = ContractRouterClient<InventoryContract>