node-type-registry 0.40.0 → 0.42.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 (39) hide show
  1. package/authz/authz-member-owner.d.ts +2 -0
  2. package/authz/authz-member-owner.js +51 -0
  3. package/authz/index.d.ts +1 -0
  4. package/authz/index.js +3 -1
  5. package/blueprint-types.generated.d.ts +289 -63
  6. package/blueprint-types.generated.js +16 -4
  7. package/codegen/generate-types.js +119 -6
  8. package/data/data-member-owner.d.ts +2 -0
  9. package/data/data-member-owner.js +53 -0
  10. package/data/index.d.ts +1 -0
  11. package/data/index.js +3 -1
  12. package/esm/authz/authz-member-owner.d.ts +2 -0
  13. package/esm/authz/authz-member-owner.js +48 -0
  14. package/esm/authz/index.d.ts +1 -0
  15. package/esm/authz/index.js +1 -0
  16. package/esm/blueprint-types.generated.d.ts +289 -63
  17. package/esm/blueprint-types.generated.js +16 -4
  18. package/esm/codegen/generate-types.js +119 -6
  19. package/esm/data/data-member-owner.d.ts +2 -0
  20. package/esm/data/data-member-owner.js +50 -0
  21. package/esm/data/index.d.ts +1 -0
  22. package/esm/data/index.js +1 -0
  23. package/esm/job/trigger.js +28 -0
  24. package/esm/module-presets/full.d.ts +6 -6
  25. package/esm/module-presets/full.js +71 -16
  26. package/esm/process/chunks.js +16 -0
  27. package/esm/process/extraction.js +16 -0
  28. package/esm/process/file-embedding.js +16 -0
  29. package/esm/process/image-embedding.js +16 -0
  30. package/esm/process/image-versions.js +16 -0
  31. package/job/trigger.js +28 -0
  32. package/module-presets/full.d.ts +6 -6
  33. package/module-presets/full.js +71 -16
  34. package/package.json +4 -4
  35. package/process/chunks.js +16 -0
  36. package/process/extraction.js +16 -0
  37. package/process/file-embedding.js +16 -0
  38. package/process/image-embedding.js +16 -0
  39. package/process/image-versions.js +16 -0
@@ -461,7 +461,7 @@ function buildBlueprintTableUniqueConstraint() {
461
461
  /**
462
462
  * Build the BlueprintBucketSeed interface.
463
463
  *
464
- * Matches the bucket entries in storage_config.buckets[].
464
+ * Matches the bucket entries in storage.buckets[].
465
465
  */
466
466
  function buildBlueprintBucketSeed() {
467
467
  return addJSDoc(exportInterface('BlueprintBucketSeed', [
@@ -471,12 +471,12 @@ function buildBlueprintBucketSeed() {
471
471
  addJSDoc(optionalProp('allowed_mime_types', t.tsArrayType(t.tsStringKeyword())), 'MIME type allowlist (e.g., ["image/png", "image/jpeg"]). NULL means all types allowed.'),
472
472
  addJSDoc(optionalProp('max_file_size', t.tsNumberKeyword()), 'Maximum file size in bytes for this bucket. NULL means no limit.'),
473
473
  addJSDoc(optionalProp('allowed_origins', t.tsArrayType(t.tsStringKeyword())), 'CORS allowed origins for this bucket.')
474
- ]), 'A bucket seed entry for storage_config.buckets[]. Creates an initial bucket row in the {prefix}_buckets table during entity type provisioning. Only used for app-level storage (not entity-scoped).');
474
+ ]), 'A bucket seed entry for storage.buckets[]. Creates an initial bucket row in the {prefix}_buckets table during entity type provisioning. Only used for app-level storage (not entity-scoped).');
475
475
  }
476
476
  /**
477
477
  * Build the BlueprintStorageConfig interface.
478
478
  *
479
- * Matches the jsonb shape accepted by storage_config on entity_type_provision.
479
+ * Matches the jsonb shape accepted by storage on entity_type_provision.
480
480
  */
481
481
  function buildBlueprintStorageConfig() {
482
482
  return addJSDoc(exportInterface('BlueprintStorageConfig', [
@@ -529,6 +529,108 @@ function buildBlueprintAchievement() {
529
529
  addJSDoc(optionalProp('entity_prefix', t.tsStringKeyword()), 'Entity prefix to scope this achievement to (e.g., "org", "app"). Used to resolve the correct events_module. Defaults to "app".')
530
530
  ]), 'An achievement entry for the blueprint achievements[] section. Creates a level with requirements and optional rewards in the events_module. Requires events_module to be provisioned (e.g., via entity_types[].has_levels = true or modules includes events_module).');
531
531
  }
532
+ // ---------------------------------------------------------------------------
533
+ // Module config types (namespace, function, agent, graph)
534
+ // ---------------------------------------------------------------------------
535
+ /**
536
+ * Build the BlueprintNamespaceConfig interface.
537
+ *
538
+ * Matches the jsonb shape accepted by namespaces on entity_type_provision
539
+ * and the top-level definition.namespaces[] array in construct_blueprint().
540
+ */
541
+ function buildBlueprintNamespaceConfig() {
542
+ return addJSDoc(exportInterface('BlueprintNamespaceConfig', [
543
+ addJSDoc(optionalProp('scope', t.tsUnionType([
544
+ t.tsLiteralType(t.stringLiteral('app')),
545
+ t.tsLiteralType(t.stringLiteral('org'))
546
+ ])), 'Namespace scope. "app" (default) creates app-level namespaces (membership_type = NULL). "org" creates per-org namespaces. Only used at the top level of a blueprint definition — entity-scoped namespaces inherit scope from the entity type.'),
547
+ addJSDoc(optionalProp('key', t.tsStringKeyword()), 'Module discriminator for multi-module namespaces. Defaults to "default" (omitted from table names). Non-default keys appear as an infix: {prefix}_{key}_namespaces.'),
548
+ addJSDoc(optionalProp('policies', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintPolicy')))), 'RLS policy overrides for the namespaces table. NULL = apply defaults from apply_namespace_security().'),
549
+ addJSDoc(optionalProp('provisions', t.tsTypeLiteral([
550
+ optionalProp('namespaces', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
551
+ optionalProp('namespace_events', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision')))
552
+ ])), 'Per-table overrides for namespace tables. Each key targets a specific table (namespaces, namespace_events) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision.')
553
+ ]), 'Namespace module configuration. When used at the top level of a blueprint, the scope field controls whether namespaces are app-level ("app", default) or org-level ("org"). When used inside entity_types[], scope is inherited from the entity type. Provisions a namespaces table with computed-name proxy, rename trigger, and entity-scoped RLS.');
554
+ }
555
+ /**
556
+ * Build the BlueprintFunctionConfig interface.
557
+ *
558
+ * Matches the jsonb shape accepted by functions on entity_type_provision
559
+ * and the top-level definition.functions[] array in construct_blueprint().
560
+ */
561
+ function buildBlueprintFunctionConfig() {
562
+ return addJSDoc(exportInterface('BlueprintFunctionConfig', [
563
+ addJSDoc(optionalProp('scope', t.tsUnionType([
564
+ t.tsLiteralType(t.stringLiteral('app')),
565
+ t.tsLiteralType(t.stringLiteral('org'))
566
+ ])), 'Function scope. "app" (default) creates app-level functions (membership_type = NULL). "org" creates per-org functions. Only used at the top level of a blueprint definition — entity-scoped functions inherit scope from the entity type.'),
567
+ addJSDoc(optionalProp('key', t.tsStringKeyword()), 'Module discriminator for multi-module functions. Defaults to "default" (omitted from table names). Non-default keys appear as an infix: {prefix}_{key}_function_definitions.'),
568
+ addJSDoc(optionalProp('policies', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintPolicy')))), 'RLS policy overrides for the function tables. NULL = apply defaults from apply_function_security().'),
569
+ addJSDoc(optionalProp('provisions', t.tsTypeLiteral([
570
+ optionalProp('definitions', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
571
+ optionalProp('invocations', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
572
+ optionalProp('execution_logs', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision')))
573
+ ])), 'Per-table overrides for function tables. Each key targets a specific table (definitions, invocations, execution_logs) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision.')
574
+ ]), 'Function module configuration. When used at the top level of a blueprint, the scope field controls whether functions are app-level ("app", default) or org-level ("org"). When used inside entity_types[], scope is inherited from the entity type. Provisions function_definitions, function_invocations (partitioned, 12-month retention), and function_execution_logs tables.');
575
+ }
576
+ /**
577
+ * Build the BlueprintAgentConfig interface.
578
+ *
579
+ * Matches the jsonb shape accepted by agents on entity_type_provision
580
+ * and the top-level definition.agents[] array in construct_blueprint().
581
+ */
582
+ function buildBlueprintAgentConfig() {
583
+ return addJSDoc(exportInterface('BlueprintAgentConfig', [
584
+ addJSDoc(optionalProp('scope', t.tsUnionType([
585
+ t.tsLiteralType(t.stringLiteral('app')),
586
+ t.tsLiteralType(t.stringLiteral('org'))
587
+ ])), 'Agent scope. "app" (default) creates app-level agent tables (membership_type = NULL). "org" creates per-org agent tables. Only used at the top level of a blueprint definition — entity-scoped agents inherit scope from the entity type.'),
588
+ addJSDoc(optionalProp('key', t.tsStringKeyword()), 'Module discriminator for multi-module agents. Defaults to "default" (omitted from table names). Non-default keys appear as an infix: {prefix}_{key}_agent_thread.'),
589
+ addJSDoc(optionalProp('api_name', t.tsStringKeyword()), 'API name for the agent module. Used in GraphQL naming. Defaults to "agent".'),
590
+ addJSDoc(optionalProp('has_knowledge', t.tsBooleanKeyword()), 'Whether to provision the agent_knowledge table with vector embeddings, tags, and trigger_phrases. Also inferred when a "knowledge" key is present. Defaults to false.'),
591
+ addJSDoc(optionalProp('knowledge', t.tsTypeLiteral([
592
+ optionalProp('has_chunks', t.tsBooleanKeyword()),
593
+ optionalProp('dimensions', t.tsNumberKeyword()),
594
+ optionalProp('chunk_size', t.tsNumberKeyword()),
595
+ optionalProp('chunk_overlap', t.tsNumberKeyword()),
596
+ optionalProp('chunk_strategy', t.tsUnionType([
597
+ t.tsLiteralType(t.stringLiteral('fixed')),
598
+ t.tsLiteralType(t.stringLiteral('sentence')),
599
+ t.tsLiteralType(t.stringLiteral('paragraph')),
600
+ t.tsLiteralType(t.stringLiteral('semantic'))
601
+ ])),
602
+ optionalProp('embedding_model', t.tsStringKeyword()),
603
+ optionalProp('embedding_provider', t.tsStringKeyword()),
604
+ optionalProp('search_indexes', t.tsArrayType(t.tsUnionType([
605
+ t.tsLiteralType(t.stringLiteral('fulltext')),
606
+ t.tsLiteralType(t.stringLiteral('bm25')),
607
+ t.tsLiteralType(t.stringLiteral('trigram'))
608
+ ])))
609
+ ])), 'Knowledge configuration overrides. Set has_chunks to false to disable the chunking pipeline. Controls vector dimensions, chunking strategy, embedding model/provider, and text search indexes for the agent_knowledge table. Presence implies has_knowledge = true.'),
610
+ addJSDoc(optionalProp('policies', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintPolicy')))), 'RLS policy overrides for the agent tables. NULL = apply defaults from apply_agent_security().'),
611
+ addJSDoc(optionalProp('provisions', t.tsTypeLiteral([
612
+ optionalProp('thread', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
613
+ optionalProp('message', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
614
+ optionalProp('task', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
615
+ optionalProp('prompt', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
616
+ optionalProp('knowledge', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision')))
617
+ ])), 'Per-table overrides for agent tables. Each key targets a specific table (thread, message, task, prompt, knowledge) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision.')
618
+ ]), 'Agent module configuration. When used at the top level of a blueprint, the scope field controls whether agents are app-level ("app", default) or org-level ("org"). When used inside entity_types[], scope is inherited from the entity type. Provisions thread, message, task, prompt tables (and optionally knowledge with vector embeddings).');
619
+ }
620
+ /**
621
+ * Build the BlueprintGraphConfig interface.
622
+ *
623
+ * Matches the jsonb shape accepted by graphs on entity_type_provision.
624
+ * Graph module requires a merkle_store_module_id dependency, so
625
+ * entity_type_provision only registers permissions. The graph module itself
626
+ * must be provisioned separately with the merkle store dependency resolved.
627
+ */
628
+ function buildBlueprintGraphConfig() {
629
+ return addJSDoc(exportInterface('BlueprintGraphConfig', [
630
+ addJSDoc(optionalProp('key', t.tsStringKeyword()), 'Module discriminator for multi-module graphs. Defaults to "default".'),
631
+ addJSDoc(optionalProp('policies', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintPolicy')))), 'RLS policy overrides for the graph tables. NULL = apply defaults from apply_graph_security().')
632
+ ]), 'Graph module configuration. Presence triggers permission registration (manage_graphs, execute_graphs). The graph module requires a merkle_store_module_id dependency, so entity_type_provision only registers permissions here — the graph module itself must be provisioned separately.');
633
+ }
532
634
  function buildBlueprintEntityTableProvision() {
533
635
  return addJSDoc(exportInterface('BlueprintEntityTableProvision', [
534
636
  addJSDoc(optionalProp('use_rls', t.tsBooleanKeyword()), 'Whether to enable RLS on the entity table. Forwarded to secure_table_provision. Defaults to true.'),
@@ -556,7 +658,11 @@ function buildBlueprintEntityType() {
556
658
  addJSDoc(optionalProp('has_invite_achievements', t.tsBooleanKeyword()), "Whether to auto-attach an EventTracker to the claimed_invites table for invite-based achievements. Requires has_invites=true AND has_levels=true. When true, records 'invite_claimed' events credited to the sender (inviter) on each claimed invite. Defaults to false."),
557
659
  addJSDoc(optionalProp('skip_entity_policies', t.tsBooleanKeyword()), 'Escape hatch: when true AND table_provision is NULL, zero policies are provisioned on the entity table. Defaults to false.'),
558
660
  addJSDoc(optionalProp('table_provision', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))), 'Override for the entity table. Shape mirrors BlueprintTable / secure_table_provision vocabulary. When supplied, its policies[] replaces the five default entity-table policies; is_visible becomes a no-op. When NULL (default), the five default policies are applied (gated by is_visible).'),
559
- addJSDoc(optionalProp('storage', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintStorageConfig')))), 'Storage module configuration array. Each entry provisions a separate storage module with its own tables, RLS, and settings. When non-empty, has_storage is derived as true. Each entry may specify a storage_key for multi-module support (defaults to "default").')
661
+ addJSDoc(optionalProp('storage', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintStorageConfig')))), 'Storage module configuration array. Presence triggers provisioning (same inference model as namespaces, functions, agents). Each entry provisions a separate storage module with its own tables, RLS, and settings. Each entry may specify a storage_key for multi-module support (defaults to "default").'),
662
+ addJSDoc(optionalProp('namespaces', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintNamespaceConfig')))), 'Namespace module configuration array. Presence triggers provisioning. Each entry provisions a namespace_module with its own tables, computed-name proxy, and entity-scoped RLS. Registers manage_namespaces permission bit. "[{}]" = provision one default namespace module.'),
663
+ addJSDoc(optionalProp('functions', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintFunctionConfig')))), 'Function module configuration array. Presence triggers provisioning. Each entry provisions function_definitions, function_invocations (partitioned), and function_execution_logs tables. Registers manage_functions + invoke_functions permission bits. "[{}]" = provision one default function module.'),
664
+ addJSDoc(optionalProp('agents', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintAgentConfig')))), 'Agent module configuration array. Presence triggers provisioning. Each entry provisions thread, message, task, prompt tables (and optionally knowledge with vector embeddings). "[{}]" = provision one default agent module.'),
665
+ addJSDoc(optionalProp('graphs', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintGraphConfig')))), 'Graph module configuration array. Presence triggers permission registration (manage_graphs, execute_graphs). Graph module requires a merkle_store_module_id dependency, so entity_type_provision only registers permissions here. "[{}]" = register default graph permissions.')
560
666
  ]), 'An entity type entry for Phase 0 of construct_blueprint(). When name is provided, provisions a new entity type with its own entity table, membership modules, and security policies via entity_type_provision. When name is omitted and only prefix is given, extends an existing entity type (e.g., the built-in "org") with additional capabilities like storage — without creating a new entity type.');
561
667
  }
562
668
  function buildBlueprintTable() {
@@ -585,7 +691,10 @@ function buildBlueprintDefinition() {
585
691
  addJSDoc(optionalProp('unique_constraints', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintUniqueConstraint')))), 'Unique constraints on table columns.'),
586
692
  addJSDoc(optionalProp('entity_types', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintEntityType')))), 'Entity types to provision in Phase 0 (before tables). Each entry creates an entity table with membership modules and security.'),
587
693
  addJSDoc(optionalProp('storage', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintStorageConfig')))), 'Top-level storage configuration array. Each entry has an optional scope ("app" or "org"). App-scoped (default) creates storage_module with membership_type = NULL. Org-scoped creates per-org/user storage with owner_id and AFTER INSERT bucket seeding. When infra is installed, a private "functions" bucket is auto-injected into org-scoped entries. For child entity type storage, use entity_types[].storage instead.'),
588
- addJSDoc(optionalProp('achievements', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintAchievement')))), 'Achievement definitions. Each entry creates a level with requirements and optional rewards in the events_module. Requires events_module to be provisioned (e.g., via entity_types[].has_levels = true or modules includes events_module).')
694
+ addJSDoc(optionalProp('achievements', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintAchievement')))), 'Achievement definitions. Each entry creates a level with requirements and optional rewards in the events_module. Requires events_module to be provisioned (e.g., via entity_types[].has_levels = true or modules includes events_module).'),
695
+ addJSDoc(optionalProp('namespaces', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintNamespaceConfig')))), 'Top-level namespace configuration array (Phase 0.6). Each entry has an optional scope ("app" or "org"). App-scoped (default) creates namespace_module with membership_type = NULL. Org-scoped creates per-org namespaces. For entity-scoped namespaces, use entity_types[].namespaces instead.'),
696
+ addJSDoc(optionalProp('functions', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintFunctionConfig')))), 'Top-level function configuration array (Phase 0.6). Each entry has an optional scope ("app" or "org"). App-scoped (default) creates function_module with membership_type = NULL. Org-scoped creates per-org functions. For entity-scoped functions, use entity_types[].functions instead.'),
697
+ addJSDoc(optionalProp('agents', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintAgentConfig')))), 'Top-level agent configuration array (Phase 0.6). Each entry has an optional scope ("app" or "org"). App-scoped (default) creates agent_module with membership_type = NULL. Org-scoped creates per-org agents. For entity-scoped agents, use entity_types[].agents instead.')
589
698
  ]), 'The complete blueprint definition -- the JSONB shape accepted by construct_blueprint().');
590
699
  }
591
700
  // ---------------------------------------------------------------------------
@@ -620,7 +729,7 @@ function buildProgram(meta) {
620
729
  statements.push(sectionComment('Shared recursive types'));
621
730
  statements.push(buildTriggerConditionInterface());
622
731
  // -- Parameter interfaces grouped by category --
623
- const categoryOrder = ['billing', 'check', 'data', 'limit', 'search', 'job', 'process', 'authz', 'relation', 'view'];
732
+ const categoryOrder = ['billing', 'check', 'data', 'event', 'limit', 'limit_enforce', 'limit_track', 'limit_warning', 'search', 'job', 'process', 'authz', 'relation', 'view'];
624
733
  for (const cat of categoryOrder) {
625
734
  const nts = categories.get(cat);
626
735
  if (!nts || nts.length === 0)
@@ -647,6 +756,10 @@ function buildProgram(meta) {
647
756
  statements.push(buildBlueprintAchievementRequirement());
648
757
  statements.push(buildBlueprintAchievementReward());
649
758
  statements.push(buildBlueprintAchievement());
759
+ statements.push(buildBlueprintNamespaceConfig());
760
+ statements.push(buildBlueprintFunctionConfig());
761
+ statements.push(buildBlueprintAgentConfig());
762
+ statements.push(buildBlueprintGraphConfig());
650
763
  statements.push(buildBlueprintEntityTableProvision());
651
764
  statements.push(buildBlueprintEntityType());
652
765
  // -- Node types discriminated union --
@@ -0,0 +1,2 @@
1
+ import type { NodeTypeDefinition } from '../types';
2
+ export declare const DataMemberOwner: NodeTypeDefinition;
@@ -0,0 +1,50 @@
1
+ export const DataMemberOwner = {
2
+ name: 'DataMemberOwner',
3
+ slug: 'data_member_owner',
4
+ category: 'data',
5
+ display_name: 'Member Owner',
6
+ description: 'Adds owner_id and entity_id columns with a compound AuthzMemberOwner policy. The actor must own the row (owner_id = current_user_id()) AND be a member of the entity (entity_id in SPRT). Use for private data within an entity scope — e.g., personal chat threads that belong to the company but only the author can see.',
7
+ parameter_schema: {
8
+ type: 'object',
9
+ properties: {
10
+ owner_field_name: {
11
+ type: 'string',
12
+ format: 'column-ref',
13
+ description: 'Column name for the owner reference',
14
+ default: 'owner_id'
15
+ },
16
+ entity_field_name: {
17
+ type: 'string',
18
+ format: 'column-ref',
19
+ description: 'Column name for the entity reference',
20
+ default: 'entity_id'
21
+ },
22
+ include_id: {
23
+ type: 'boolean',
24
+ description: 'If true, also adds a UUID primary key column with auto-generation',
25
+ default: true
26
+ },
27
+ include_user_fk: {
28
+ type: 'boolean',
29
+ description: 'If true, adds foreign key constraints from owner_id and entity_id to the users table',
30
+ default: true
31
+ },
32
+ create_index: {
33
+ type: 'boolean',
34
+ description: 'If true, creates B-tree indexes on the owner and entity columns',
35
+ default: true
36
+ },
37
+ membership_type: {
38
+ type: 'integer',
39
+ description: 'Membership type for SPRT resolution. Required for entity-scoped provisioning.',
40
+ default: null
41
+ }
42
+ }
43
+ },
44
+ tags: [
45
+ 'ownership',
46
+ 'membership',
47
+ 'security',
48
+ 'schema'
49
+ ]
50
+ };
@@ -12,6 +12,7 @@ export { DataImmutableFields } from './data-immutable-fields';
12
12
  export { DataInflection } from './data-inflection';
13
13
  export { DataInheritFromParent } from './data-inherit-from-parent';
14
14
  export { DataJsonb } from './data-jsonb';
15
+ export { DataMemberOwner } from './data-member-owner';
15
16
  export { DataOwnedFields } from './data-owned-fields';
16
17
  export { DataOwnershipInEntity } from './data-ownership-in-entity';
17
18
  export { DataPeoplestamps } from './data-peoplestamps';
package/esm/data/index.js CHANGED
@@ -12,6 +12,7 @@ export { DataImmutableFields } from './data-immutable-fields';
12
12
  export { DataInflection } from './data-inflection';
13
13
  export { DataInheritFromParent } from './data-inherit-from-parent';
14
14
  export { DataJsonb } from './data-jsonb';
15
+ export { DataMemberOwner } from './data-member-owner';
15
16
  export { DataOwnedFields } from './data-owned-fields';
16
17
  export { DataOwnershipInEntity } from './data-ownership-in-entity';
17
18
  export { DataPeoplestamps } from './data-peoplestamps';
@@ -67,6 +67,34 @@ export const JobTrigger = {
67
67
  default: false
68
68
  },
69
69
  ...conditionProperties,
70
+ entity_field: {
71
+ type: 'string',
72
+ format: 'column-ref',
73
+ description: 'Column on the trigger table that holds (or references) the entity_id for billing scope. For direct entity_id columns, just set this field. For FK lookups (e.g., channel_id → channels.entity_id), combine with entity_lookup.'
74
+ },
75
+ entity_lookup: {
76
+ type: 'object',
77
+ description: 'FK lookup configuration for resolving entity_id through a related table. Used when entity_field is a FK (e.g., channel_id) rather than a direct entity_id. The generator validates all fields against metaschema within the same database_id.',
78
+ properties: {
79
+ obj_table: {
80
+ type: 'string',
81
+ description: 'Name of the related table to look up entity_id from (e.g., "channels"). Required.'
82
+ },
83
+ obj_schema: {
84
+ type: 'string',
85
+ description: 'Schema of the related table (user-facing name, e.g., "public"). Optional — if omitted, resolved by table name within the same database_id (raises error if ambiguous).'
86
+ },
87
+ obj_field: {
88
+ type: 'string',
89
+ format: 'column-ref',
90
+ description: 'Column on the related table that holds the entity_id (e.g., "entity_id"). Required.'
91
+ }
92
+ },
93
+ required: [
94
+ 'obj_table',
95
+ 'obj_field'
96
+ ]
97
+ },
70
98
  job_key: {
71
99
  type: 'string',
72
100
  description: 'Static job key for upsert semantics (prevents duplicate jobs)'
@@ -1,13 +1,13 @@
1
1
  import type { ModulePreset } from './types';
2
2
  /**
3
- * `full` — install everything. Equivalent to the default
4
- * `provision_database_modules(v_modules => ARRAY['all'])` behavior.
3
+ * `full` — install every standard module.
5
4
  *
6
5
  * This is the maximalist preset: every module Constructive ships, including
7
- * `storage_module` for file uploads and `crypto_addresses_module` for
8
- * wallet-based sign-in. Use it for greenfield apps where you'd rather
9
- * disable features via `app_settings_auth` toggles than uninstall modules,
10
- * or for the "kitchen sink" example / demo databases.
6
+ * `storage_module:full` for file uploads with all feature flags and
7
+ * `crypto_addresses_module` for wallet-based sign-in.
8
+ *
9
+ * Usage logging modules (compute_log, inference_log, transfer_log,
10
+ * storage_log, db_usage) are NOT included — they are opt-in only.
11
11
  *
12
12
  * Prefer a more targeted preset for anything production-bound — installing
13
13
  * a module you'll never use still costs tables, triggers, and grants.
@@ -1,12 +1,12 @@
1
1
  /**
2
- * `full` — install everything. Equivalent to the default
3
- * `provision_database_modules(v_modules => ARRAY['all'])` behavior.
2
+ * `full` — install every standard module.
4
3
  *
5
4
  * This is the maximalist preset: every module Constructive ships, including
6
- * `storage_module` for file uploads and `crypto_addresses_module` for
7
- * wallet-based sign-in. Use it for greenfield apps where you'd rather
8
- * disable features via `app_settings_auth` toggles than uninstall modules,
9
- * or for the "kitchen sink" example / demo databases.
5
+ * `storage_module:full` for file uploads with all feature flags and
6
+ * `crypto_addresses_module` for wallet-based sign-in.
7
+ *
8
+ * Usage logging modules (compute_log, inference_log, transfer_log,
9
+ * storage_log, db_usage) are NOT included — they are opt-in only.
10
10
  *
11
11
  * Prefer a more targeted preset for anything production-bound — installing
12
12
  * a module you'll never use still costs tables, triggers, and grants.
@@ -14,25 +14,80 @@
14
14
  export const PresetFull = {
15
15
  name: 'full',
16
16
  display_name: 'Full (every module)',
17
- summary: "Install every Constructive module. Equivalent to v_modules => ARRAY['all'].",
18
- description: 'Installs every module in the catalog: everything in `b2b` plus `storage_module` ' +
19
- 'for file uploads and `crypto_addresses_module` / `crypto_auth_module` for ' +
20
- 'wallet-based sign-in. This matches the current default when `provision_database_modules` ' +
21
- 'is called without an explicit `v_modules` argument. Use it for fully-featured ' +
22
- 'demo/example databases, kitchen-sink reference deployments, or greenfield apps that ' +
23
- 'would rather feature-flag at the app_settings level than uninstall modules.',
17
+ summary: 'Install every standard Constructive module with explicit module list.',
18
+ description: 'Installs every standard module in the catalog: everything in `b2b` plus ' +
19
+ '`storage_module:full` for file uploads (versioning, content hash, custom keys, audit log), ' +
20
+ '`crypto_addresses_module` for wallet-based sign-in, `plans_module` and `billing_module` ' +
21
+ 'for subscription management, `notifications_module` for in-app notifications, and ' +
22
+ '`events_module` at both app and org scopes. Usage logging modules are opt-in only — ' +
23
+ 'add them explicitly if needed.',
24
24
  good_for: [
25
25
  'Reference / demo databases that showcase every Constructive feature',
26
26
  'Greenfield apps where the product scope is still open-ended',
27
- 'Keeping the provisioning call identical to the pre-preset default'
27
+ 'Integration tests that need the full module stack'
28
28
  ],
29
29
  not_for: [
30
30
  'Production apps with a defined feature set — pick the narrowest preset that fits',
31
31
  'Resource-constrained environments — every module costs schema bloat, RLS policies, and grants'
32
32
  ],
33
- modules: ['all'],
33
+ modules: [
34
+ // Core
35
+ 'users_module',
36
+ 'membership_types_module',
37
+ // App-level (membership_type = 1)
38
+ 'permissions_module:app',
39
+ 'limits_module:app',
40
+ 'memberships_module:app',
41
+ 'events_module:app',
42
+ 'profiles_module:app',
43
+ // Org-level (membership_type = 2)
44
+ 'permissions_module:org',
45
+ 'limits_module:org',
46
+ 'memberships_module:org',
47
+ 'events_module:org',
48
+ 'profiles_module:org',
49
+ // Hierarchy
50
+ 'hierarchy_module:org',
51
+ // Billing & Plans
52
+ 'plans_module',
53
+ 'billing_module',
54
+ 'rate_limit_meters_module',
55
+ 'billing_provider_module',
56
+ // Auth infrastructure
57
+ 'user_state_module',
58
+ 'sessions_module',
59
+ 'session_secrets_module',
60
+ 'rate_limits_module',
61
+ 'devices_module',
62
+ 'config_secrets_user_module',
63
+ 'rls_module',
64
+ // Contact modules
65
+ 'emails_module',
66
+ 'phone_numbers_module',
67
+ 'crypto_addresses_module',
68
+ 'webauthn_credentials_module',
69
+ 'notifications_module',
70
+ // Connected accounts
71
+ 'connected_accounts_module',
72
+ 'identity_providers_module',
73
+ // Invites & Auth
74
+ 'invites_module:app',
75
+ 'invites_module:org',
76
+ 'user_auth_module',
77
+ 'webauthn_auth_module',
78
+ // Storage (full features)
79
+ 'storage_module:full',
80
+ ],
34
81
  includes_notes: {
35
- all: "Sentinel the provisioner installs every known module when `modules = ['all']`."
82
+ 'storage_module:full': 'All storage feature flags enabled: versioning, content hash, custom keys, audit log.',
83
+ billing_module: 'Metered billing with credits waterfall and period reset.',
84
+ plans_module: 'Subscription plan management with plan-governed caps.',
85
+ notifications_module: 'In-app notification system with read/unread tracking.'
86
+ },
87
+ omits_notes: {
88
+ compute_log_module: 'Usage logging is opt-in. Add explicitly if needed.',
89
+ inference_log_module: 'Usage logging is opt-in. Add explicitly if needed.',
90
+ agent_module: 'Agent infrastructure is opt-in.'
36
91
  },
37
92
  extends: ['b2b']
38
93
  };
@@ -93,6 +93,22 @@ export const ProcessChunks = {
93
93
  'Omit to mirror the parent table\'s text search indexes. ' +
94
94
  'Set explicitly to override (e.g. ["fulltext", "bm25"]).'
95
95
  },
96
+ // ── Entity billing scope ──────────────────────────────────────
97
+ entity_field: {
98
+ type: 'string',
99
+ format: 'column-ref',
100
+ description: 'Column on the parent table that holds (or references) the entity_id for billing scope. Forwarded to the chunking job trigger.'
101
+ },
102
+ entity_lookup: {
103
+ type: 'object',
104
+ description: 'FK lookup configuration for resolving entity_id through a related table. Forwarded to the chunking job trigger.',
105
+ properties: {
106
+ obj_table: { type: 'string', description: 'Name of the related table to look up entity_id from' },
107
+ obj_schema: { type: 'string', description: 'Schema of the related table (user-facing name, optional)' },
108
+ obj_field: { type: 'string', format: 'column-ref', description: 'Column on the related table that holds the entity_id' }
109
+ },
110
+ required: ['obj_table', 'obj_field']
111
+ },
96
112
  // ── Job trigger ────────────────────────────────────────────────
97
113
  enqueue_chunking_job: {
98
114
  type: 'boolean',
@@ -82,6 +82,22 @@ export const ProcessExtraction = {
82
82
  }
83
83
  },
84
84
  trigger_conditions: triggerConditionsProperty,
85
+ // ── Entity billing scope ──────────────────────────────────────
86
+ entity_field: {
87
+ type: 'string',
88
+ format: 'column-ref',
89
+ description: 'Column on the trigger table that holds (or references) the entity_id for billing scope. Forwarded to the composed JobTrigger.'
90
+ },
91
+ entity_lookup: {
92
+ type: 'object',
93
+ description: 'FK lookup configuration for resolving entity_id through a related table. Forwarded to the composed JobTrigger.',
94
+ properties: {
95
+ obj_table: { type: 'string', description: 'Name of the related table to look up entity_id from' },
96
+ obj_schema: { type: 'string', description: 'Schema of the related table (user-facing name, optional)' },
97
+ obj_field: { type: 'string', format: 'column-ref', description: 'Column on the related table that holds the entity_id' }
98
+ },
99
+ required: ['obj_table', 'obj_field']
100
+ },
85
101
  // ── Job options ───────────────────────────────────────────────
86
102
  queue_name: {
87
103
  type: 'string',
@@ -89,6 +89,22 @@ export const ProcessFileEmbedding = {
89
89
  }
90
90
  },
91
91
  trigger_conditions: triggerConditionsProperty,
92
+ // ── Entity billing scope ──────────────────────────────────────
93
+ entity_field: {
94
+ type: 'string',
95
+ format: 'column-ref',
96
+ description: 'Column on the trigger table that holds (or references) the entity_id for billing scope. Forwarded to the composed JobTrigger.'
97
+ },
98
+ entity_lookup: {
99
+ type: 'object',
100
+ description: 'FK lookup configuration for resolving entity_id through a related table. Forwarded to the composed JobTrigger.',
101
+ properties: {
102
+ obj_table: { type: 'string', description: 'Name of the related table to look up entity_id from' },
103
+ obj_schema: { type: 'string', description: 'Schema of the related table (user-facing name, optional)' },
104
+ obj_field: { type: 'string', format: 'column-ref', description: 'Column on the related table that holds the entity_id' }
105
+ },
106
+ required: ['obj_table', 'obj_field']
107
+ },
92
108
  // ── Extraction config (optional — enables extract mode) ────────
93
109
  extraction: {
94
110
  type: 'object',
@@ -96,6 +96,22 @@ export const ProcessImageEmbedding = {
96
96
  }
97
97
  },
98
98
  trigger_conditions: triggerConditionsProperty,
99
+ // ── Entity billing scope ──────────────────────────────────────
100
+ entity_field: {
101
+ type: 'string',
102
+ format: 'column-ref',
103
+ description: 'Column on the trigger table that holds (or references) the entity_id for billing scope. Forwarded to the composed JobTrigger.'
104
+ },
105
+ entity_lookup: {
106
+ type: 'object',
107
+ description: 'FK lookup configuration for resolving entity_id through a related table. Forwarded to the composed JobTrigger.',
108
+ properties: {
109
+ obj_table: { type: 'string', description: 'Name of the related table to look up entity_id from' },
110
+ obj_schema: { type: 'string', description: 'Schema of the related table (user-facing name, optional)' },
111
+ obj_field: { type: 'string', format: 'column-ref', description: 'Column on the related table that holds the entity_id' }
112
+ },
113
+ required: ['obj_table', 'obj_field']
114
+ },
99
115
  // ── Extraction config (optional — enables extract mode) ────────
100
116
  extraction: {
101
117
  type: 'object',
@@ -101,6 +101,22 @@ export const ProcessImageVersions = {
101
101
  }
102
102
  },
103
103
  trigger_conditions: triggerConditionsProperty,
104
+ // ── Entity billing scope ──────────────────────────────────────
105
+ entity_field: {
106
+ type: 'string',
107
+ format: 'column-ref',
108
+ description: 'Column on the trigger table that holds (or references) the entity_id for billing scope. Forwarded to the composed JobTrigger.'
109
+ },
110
+ entity_lookup: {
111
+ type: 'object',
112
+ description: 'FK lookup configuration for resolving entity_id through a related table. Forwarded to the composed JobTrigger.',
113
+ properties: {
114
+ obj_table: { type: 'string', description: 'Name of the related table to look up entity_id from' },
115
+ obj_schema: { type: 'string', description: 'Schema of the related table (user-facing name, optional)' },
116
+ obj_field: { type: 'string', format: 'column-ref', description: 'Column on the related table that holds the entity_id' }
117
+ },
118
+ required: ['obj_table', 'obj_field']
119
+ },
104
120
  // ── Job options ───────────────────────────────────────────────
105
121
  queue_name: {
106
122
  type: 'string',
package/job/trigger.js CHANGED
@@ -70,6 +70,34 @@ exports.JobTrigger = {
70
70
  default: false
71
71
  },
72
72
  ...conditions_1.conditionProperties,
73
+ entity_field: {
74
+ type: 'string',
75
+ format: 'column-ref',
76
+ description: 'Column on the trigger table that holds (or references) the entity_id for billing scope. For direct entity_id columns, just set this field. For FK lookups (e.g., channel_id → channels.entity_id), combine with entity_lookup.'
77
+ },
78
+ entity_lookup: {
79
+ type: 'object',
80
+ description: 'FK lookup configuration for resolving entity_id through a related table. Used when entity_field is a FK (e.g., channel_id) rather than a direct entity_id. The generator validates all fields against metaschema within the same database_id.',
81
+ properties: {
82
+ obj_table: {
83
+ type: 'string',
84
+ description: 'Name of the related table to look up entity_id from (e.g., "channels"). Required.'
85
+ },
86
+ obj_schema: {
87
+ type: 'string',
88
+ description: 'Schema of the related table (user-facing name, e.g., "public"). Optional — if omitted, resolved by table name within the same database_id (raises error if ambiguous).'
89
+ },
90
+ obj_field: {
91
+ type: 'string',
92
+ format: 'column-ref',
93
+ description: 'Column on the related table that holds the entity_id (e.g., "entity_id"). Required.'
94
+ }
95
+ },
96
+ required: [
97
+ 'obj_table',
98
+ 'obj_field'
99
+ ]
100
+ },
73
101
  job_key: {
74
102
  type: 'string',
75
103
  description: 'Static job key for upsert semantics (prevents duplicate jobs)'
@@ -1,13 +1,13 @@
1
1
  import type { ModulePreset } from './types';
2
2
  /**
3
- * `full` — install everything. Equivalent to the default
4
- * `provision_database_modules(v_modules => ARRAY['all'])` behavior.
3
+ * `full` — install every standard module.
5
4
  *
6
5
  * This is the maximalist preset: every module Constructive ships, including
7
- * `storage_module` for file uploads and `crypto_addresses_module` for
8
- * wallet-based sign-in. Use it for greenfield apps where you'd rather
9
- * disable features via `app_settings_auth` toggles than uninstall modules,
10
- * or for the "kitchen sink" example / demo databases.
6
+ * `storage_module:full` for file uploads with all feature flags and
7
+ * `crypto_addresses_module` for wallet-based sign-in.
8
+ *
9
+ * Usage logging modules (compute_log, inference_log, transfer_log,
10
+ * storage_log, db_usage) are NOT included — they are opt-in only.
11
11
  *
12
12
  * Prefer a more targeted preset for anything production-bound — installing
13
13
  * a module you'll never use still costs tables, triggers, and grants.