node-type-registry 0.44.0 → 0.47.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 (40) hide show
  1. package/README.md +4 -0
  2. package/blueprint-types.generated.d.ts +62 -37
  3. package/codegen/generate-types.js +16 -7
  4. package/data/data-i18n.d.ts +2 -0
  5. package/data/data-i18n.js +47 -0
  6. package/data/index.d.ts +1 -0
  7. package/data/index.js +3 -1
  8. package/esm/blueprint-types.generated.d.ts +62 -37
  9. package/esm/codegen/generate-types.js +16 -7
  10. package/esm/data/data-i18n.d.ts +2 -0
  11. package/esm/data/data-i18n.js +44 -0
  12. package/esm/data/index.d.ts +1 -0
  13. package/esm/data/index.js +1 -0
  14. package/esm/module-presets/auth-email-magic.js +6 -14
  15. package/esm/module-presets/auth-email.d.ts +3 -3
  16. package/esm/module-presets/auth-email.js +10 -29
  17. package/esm/module-presets/auth-hardened.js +6 -21
  18. package/esm/module-presets/auth-passkey.js +6 -15
  19. package/esm/module-presets/auth-sso.d.ts +1 -1
  20. package/esm/module-presets/auth-sso.js +8 -18
  21. package/esm/module-presets/b2b-storage.js +16 -22
  22. package/esm/module-presets/b2b.js +20 -38
  23. package/esm/module-presets/full.d.ts +1 -1
  24. package/esm/module-presets/full.js +25 -28
  25. package/esm/module-presets/minimal.js +1 -12
  26. package/esm/module-presets/types.d.ts +9 -15
  27. package/module-presets/auth-email-magic.js +6 -14
  28. package/module-presets/auth-email.d.ts +3 -3
  29. package/module-presets/auth-email.js +10 -29
  30. package/module-presets/auth-hardened.js +6 -21
  31. package/module-presets/auth-passkey.js +6 -15
  32. package/module-presets/auth-sso.d.ts +1 -1
  33. package/module-presets/auth-sso.js +8 -18
  34. package/module-presets/b2b-storage.js +16 -22
  35. package/module-presets/b2b.js +20 -38
  36. package/module-presets/full.d.ts +1 -1
  37. package/module-presets/full.js +25 -28
  38. package/module-presets/minimal.js +1 -12
  39. package/module-presets/types.d.ts +9 -15
  40. package/package.json +2 -2
@@ -106,6 +106,13 @@ export interface DataEntityMembershipParams {
106
106
  export interface DataForceCurrentUserParams {
107
107
  field_name?: string;
108
108
  }
109
+ /** Creates a companion _translations table with lang_code + translatable fields. Copies SELECT policies and column-ref fields from the base table. Adds @i18n smart comment so the Graphile i18n plugin discovers it. Requires i18n_module to be provisioned for the database. */
110
+ export interface DataI18nParams {
111
+ fields: string[];
112
+ table_suffix?: string;
113
+ lang_code_type?: 'citext' | 'text';
114
+ copy_mutation_policies?: boolean;
115
+ }
109
116
  /** Adds a UUID primary key column with auto-generation default (uuidv7). This is the standard primary key pattern for all tables. */
110
117
  export interface DataIdParams {
111
118
  field_name?: string;
@@ -664,16 +671,6 @@ export interface AuthzCompositeParams {
664
671
  }
665
672
  /** Denies all access. Generates FALSE expression. */
666
673
  export type AuthzDenyAllParams = {};
667
- /** Path-scoped file sharing via ltree containment. Grants access when a path_shares row matches the current user, bucket, and an ancestor path with the required permission. */
668
- export interface AuthzFilePathParams {
669
- shares_schema: string;
670
- shares_table: string;
671
- files_schema?: string;
672
- files_table: string;
673
- permission_field: string;
674
- bucket_field?: string;
675
- path_field?: string;
676
- }
677
674
  /** Direct equality comparison between a table column and the current user ID. Simplest authorization pattern with no subqueries. */
678
675
  export interface AuthzDirectOwnerParams {
679
676
  entity_field: string;
@@ -693,10 +690,30 @@ export interface AuthzEntityMembershipParams {
693
690
  is_admin?: boolean;
694
691
  is_owner?: boolean;
695
692
  }
693
+ /** Path-scoped file sharing via ltree containment. Grants access when a path_shares row matches the current user, bucket, and an ancestor path with the required permission. */
694
+ export interface AuthzFilePathParams {
695
+ shares_schema: string;
696
+ shares_table: string;
697
+ files_schema?: string;
698
+ files_table: string;
699
+ permission_field: string;
700
+ bucket_field?: string;
701
+ path_field?: string;
702
+ }
696
703
  /** Check if current user is in an array column on the same row. */
697
704
  export interface AuthzMemberListParams {
698
705
  array_field: string;
699
706
  }
707
+ /** Compound policy: the row must be owned by the current user (owner_field = current_user_id) AND the current user must be a member of the entity referenced by entity_field. Combines direct ownership with entity membership — the actor can only access rows they own within entities they belong to. */
708
+ export interface AuthzMemberOwnerParams {
709
+ owner_field: string;
710
+ entity_field: string;
711
+ sel_field?: string;
712
+ membership_type?: number | string;
713
+ entity_type?: string;
714
+ permission?: string;
715
+ permissions?: string[];
716
+ }
700
717
  /** Restrictive policy that blocks read-only members from mutations. Checks actor_id + is_read_only IS NOT TRUE on the SPRT. Designed to run as a restrictive counterpart after a permissive AuthzEntityMembership policy has already verified membership. */
701
718
  export interface AuthzNotReadOnlyParams {
702
719
  entity_field: string;
@@ -709,16 +726,6 @@ export interface AuthzOrgHierarchyParams {
709
726
  anchor_field: string;
710
727
  max_depth?: number;
711
728
  }
712
- /** Compound policy: the row must be owned by the current user (owner_field = current_user_id) AND the current user must be a member of the entity referenced by entity_field. Combines direct ownership with entity membership — the actor can only access rows they own within entities they belong to. */
713
- export interface AuthzMemberOwnerParams {
714
- owner_field: string;
715
- entity_field: string;
716
- sel_field?: string;
717
- membership_type?: number | string;
718
- entity_type?: string;
719
- permission?: string;
720
- permissions?: string[];
721
- }
722
729
  /** Peer visibility through shared entity membership. Authorizes access to user-owned rows when the owner and current user are both members of the same entity. Self-joins the SPRT table to find peers. */
723
730
  export interface AuthzPeerOwnershipParams {
724
731
  owner_field: string;
@@ -905,7 +912,7 @@ export interface BlueprintField {
905
912
  /** An RLS policy entry for a blueprint table. Uses $type to match the blueprint JSON convention. */
906
913
  export interface BlueprintPolicy {
907
914
  /** Authz* policy type name (e.g., "AuthzDirectOwner", "AuthzAllowAll"). */
908
- $type: 'AuthzAllowAll' | 'AuthzAppMembership' | 'AuthzComposite' | 'AuthzDenyAll' | 'AuthzFilePath' | 'AuthzDirectOwner' | 'AuthzDirectOwnerAny' | 'AuthzEntityMembership' | 'AuthzMemberList' | 'AuthzNotReadOnly' | 'AuthzOrgHierarchy' | 'AuthzMemberOwner' | 'AuthzPeerOwnership' | 'AuthzPublishable' | 'AuthzRelatedEntityMembership' | 'AuthzRelatedMemberList' | 'AuthzRelatedPeerOwnership' | 'AuthzTemporal';
915
+ $type: 'AuthzAllowAll' | 'AuthzAppMembership' | 'AuthzComposite' | 'AuthzDenyAll' | 'AuthzDirectOwner' | 'AuthzDirectOwnerAny' | 'AuthzEntityMembership' | 'AuthzFilePath' | 'AuthzMemberList' | 'AuthzMemberOwner' | 'AuthzNotReadOnly' | 'AuthzOrgHierarchy' | 'AuthzPeerOwnership' | 'AuthzPublishable' | 'AuthzRelatedEntityMembership' | 'AuthzRelatedMemberList' | 'AuthzRelatedPeerOwnership' | 'AuthzTemporal';
909
916
  /** Privileges this policy applies to (e.g., ["select"], ["insert", "update", "delete"]). */
910
917
  privileges?: string[];
911
918
  /** Whether this policy is permissive (true) or restrictive (false). Defaults to true. */
@@ -1023,6 +1030,8 @@ export interface BlueprintStorageConfig {
1023
1030
  scope?: 'app' | 'org';
1024
1031
  /** Discriminator for multi-module storage. Defaults to "default" (omitted from table names). Non-default keys appear as an infix: {prefix}_{storage_key}_buckets. Max 16 chars, lowercase snake_case. */
1025
1032
  storage_key?: string;
1033
+ /** Override the table-name prefix. By default the prefix is derived from the scope (e.g. "org"). Set to an empty string to produce unprefixed table names (e.g. "buckets" instead of "org_buckets"). */
1034
+ prefix?: string;
1026
1035
  /** Initial bucket seed entries. Each creates a row in {prefix}_buckets during provisioning. */
1027
1036
  buckets?: BlueprintBucketSeed[];
1028
1037
  /** Override for presigned upload URL expiry time in seconds. */
@@ -1084,6 +1093,8 @@ export interface BlueprintNamespaceConfig {
1084
1093
  scope?: 'app' | 'org';
1085
1094
  /** Module discriminator for multi-module namespaces. Defaults to "default" (omitted from table names). Non-default keys appear as an infix: {prefix}_{key}_namespaces. */
1086
1095
  key?: string;
1096
+ /** Override the table-name prefix. By default the prefix is derived from the scope (e.g. "org"). Set to an empty string to produce unprefixed table names (e.g. "namespaces" instead of "org_namespaces"). */
1097
+ prefix?: string;
1087
1098
  /** RLS policy overrides for the namespaces table. NULL = apply defaults from apply_namespace_security(). */
1088
1099
  policies?: BlueprintPolicy[];
1089
1100
  /** 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. */
@@ -1098,6 +1109,8 @@ export interface BlueprintFunctionConfig {
1098
1109
  scope?: 'app' | 'org';
1099
1110
  /** Module discriminator for multi-module functions. Defaults to "default" (omitted from table names). Non-default keys appear as an infix: {prefix}_{key}_function_definitions. */
1100
1111
  key?: string;
1112
+ /** Override the table-name prefix. By default the prefix is derived from the scope (e.g. "org"). Set to an empty string to produce unprefixed table names (e.g. "function_definitions" instead of "org_function_definitions"). */
1113
+ prefix?: string;
1101
1114
  /** RLS policy overrides for the function tables. NULL = apply defaults from apply_function_security(). */
1102
1115
  policies?: BlueprintPolicy[];
1103
1116
  /** 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. */
@@ -1107,18 +1120,24 @@ export interface BlueprintFunctionConfig {
1107
1120
  execution_logs?: BlueprintEntityTableProvision;
1108
1121
  };
1109
1122
  }
1110
- /** 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). */
1123
+ /** 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. Opt-in: has_plans (plan + approval workflow), has_resources (unified skills/knowledge with chunking), has_agents (agent registry + personas, implies has_resources). */
1111
1124
  export interface BlueprintAgentConfig {
1112
1125
  /** 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. */
1113
1126
  scope?: 'app' | 'org';
1114
1127
  /** Module discriminator for multi-module agents. Defaults to "default" (omitted from table names). Non-default keys appear as an infix: {prefix}_{key}_agent_thread. */
1115
1128
  key?: string;
1129
+ /** Override the table-name prefix. By default the prefix is derived from the scope (e.g. "org"). Set to an empty string to produce unprefixed table names (e.g. "agent_thread" instead of "org_agent_thread"). */
1130
+ prefix?: string;
1116
1131
  /** API name for the agent module. Used in GraphQL naming. Defaults to "agent". */
1117
1132
  api_name?: string;
1118
- /** 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. */
1119
- has_knowledge?: boolean;
1120
- /** 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. */
1121
- knowledge?: {
1133
+ /** Whether to provision the agent_plan table for workflow plans with ordered tasks and approval gates. When true, tasks belong to plans (plan_id NOT NULL) instead of directly to threads. Defaults to false. */
1134
+ has_plans?: boolean;
1135
+ /** Whether to provision the unified agent_resource table (kind: skill/knowledge/convention) with auto-chunking (ProcessChunks) and vector embeddings. Defaults to false. */
1136
+ has_resources?: boolean;
1137
+ /** Whether to provision agent + agent_persona tables for agent registry and templates. Implies has_resources. Defaults to false. */
1138
+ has_agents?: boolean;
1139
+ /** Resource configuration array. Controls vector dimensions, chunking strategy, embedding model/provider, and text search indexes for the agent_resource table. Set has_chunks to false to disable the ProcessChunks pipeline. Defaults: 768 dimensions, 1000 chunk_size, 200 chunk_overlap, paragraph strategy, ["tsvector"] search indexes. */
1140
+ resources?: {
1122
1141
  has_chunks?: boolean;
1123
1142
  dimensions?: number;
1124
1143
  chunk_size?: number;
@@ -1126,17 +1145,20 @@ export interface BlueprintAgentConfig {
1126
1145
  chunk_strategy?: 'fixed' | 'sentence' | 'paragraph' | 'semantic';
1127
1146
  embedding_model?: string;
1128
1147
  embedding_provider?: string;
1129
- search_indexes?: ('fulltext' | 'bm25' | 'trigram')[];
1130
- };
1148
+ search_indexes?: ('tsvector' | 'bm25' | 'trigram')[];
1149
+ }[];
1131
1150
  /** RLS policy overrides for the agent tables. NULL = apply defaults from apply_agent_security(). */
1132
1151
  policies?: BlueprintPolicy[];
1133
- /** 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. */
1152
+ /** Per-table overrides for agent tables. Each key targets a specific table (thread, message, task, prompt, plan, resource, agent, persona) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision. */
1134
1153
  provisions?: {
1135
1154
  thread?: BlueprintEntityTableProvision;
1136
1155
  message?: BlueprintEntityTableProvision;
1137
1156
  task?: BlueprintEntityTableProvision;
1138
1157
  prompt?: BlueprintEntityTableProvision;
1139
- knowledge?: BlueprintEntityTableProvision;
1158
+ plan?: BlueprintEntityTableProvision;
1159
+ resource?: BlueprintEntityTableProvision;
1160
+ agent?: BlueprintEntityTableProvision;
1161
+ persona?: BlueprintEntityTableProvision;
1140
1162
  };
1141
1163
  }
1142
1164
  /** 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. */
@@ -1202,7 +1224,7 @@ export interface BlueprintEntityType {
1202
1224
  graphs?: BlueprintGraphConfig[];
1203
1225
  }
1204
1226
  /** String shorthand -- just the node type name. */
1205
- export type BlueprintNodeShorthand = 'AuthzAllowAll' | 'AuthzAppMembership' | 'AuthzComposite' | 'AuthzDenyAll' | 'AuthzFilePath' | 'AuthzDirectOwner' | 'AuthzDirectOwnerAny' | 'AuthzEntityMembership' | 'AuthzMemberList' | 'AuthzNotReadOnly' | 'AuthzOrgHierarchy' | 'AuthzMemberOwner' | 'AuthzPeerOwnership' | 'AuthzPublishable' | 'AuthzRelatedEntityMembership' | 'AuthzRelatedMemberList' | 'AuthzRelatedPeerOwnership' | 'AuthzTemporal' | 'CheckGreaterThan' | 'CheckLessThan' | 'CheckNotEqual' | 'CheckOneOf' | 'DataBulk' | 'DataCompositeField' | 'DataDirectOwner' | 'DataEntityMembership' | 'DataForceCurrentUser' | 'DataId' | 'DataImmutableFields' | 'DataInflection' | 'DataInheritFromParent' | 'DataJsonb' | 'DataMemberOwner' | 'DataOwnedFields' | 'DataOwnershipInEntity' | 'DataPeoplestamps' | 'DataPublishable' | 'DataRealtime' | 'DataSlug' | 'DataSoftDelete' | 'DataStatusField' | 'DataTags' | 'DataTimestamps' | 'SearchBm25' | 'SearchFullText' | 'SearchSpatial' | 'SearchSpatialAggregate' | 'SearchTrgm' | 'SearchUnified' | 'SearchVector' | 'TableOrganizationSettings' | 'TableUserProfiles' | 'TableUserSettings' | 'EventReferral' | 'EventTracker' | 'JobTrigger' | 'LimitEnforceAggregate' | 'LimitEnforceCounter' | 'LimitEnforceFeature' | 'LimitEnforceRate' | 'LimitTrackUsage' | 'LimitWarningAggregate' | 'LimitWarningCounter' | 'LimitWarningRate' | 'ProcessChunks' | 'ProcessExtraction' | 'ProcessFileEmbedding' | 'ProcessImageEmbedding' | 'ProcessImageVersions';
1227
+ export type BlueprintNodeShorthand = 'AuthzAllowAll' | 'AuthzAppMembership' | 'AuthzComposite' | 'AuthzDenyAll' | 'AuthzDirectOwner' | 'AuthzDirectOwnerAny' | 'AuthzEntityMembership' | 'AuthzFilePath' | 'AuthzMemberList' | 'AuthzMemberOwner' | 'AuthzNotReadOnly' | 'AuthzOrgHierarchy' | 'AuthzPeerOwnership' | 'AuthzPublishable' | 'AuthzRelatedEntityMembership' | 'AuthzRelatedMemberList' | 'AuthzRelatedPeerOwnership' | 'AuthzTemporal' | 'CheckGreaterThan' | 'CheckLessThan' | 'CheckNotEqual' | 'CheckOneOf' | 'DataBulk' | 'DataCompositeField' | 'DataDirectOwner' | 'DataEntityMembership' | 'DataForceCurrentUser' | 'DataI18n' | 'DataId' | 'DataImmutableFields' | 'DataInflection' | 'DataInheritFromParent' | 'DataJsonb' | 'DataMemberOwner' | 'DataOwnedFields' | 'DataOwnershipInEntity' | 'DataPeoplestamps' | 'DataPublishable' | 'DataRealtime' | 'DataSlug' | 'DataSoftDelete' | 'DataStatusField' | 'DataTags' | 'DataTimestamps' | 'SearchBm25' | 'SearchFullText' | 'SearchSpatial' | 'SearchSpatialAggregate' | 'SearchTrgm' | 'SearchUnified' | 'SearchVector' | 'TableOrganizationSettings' | 'TableUserProfiles' | 'TableUserSettings' | 'EventReferral' | 'EventTracker' | 'JobTrigger' | 'LimitEnforceAggregate' | 'LimitEnforceCounter' | 'LimitEnforceFeature' | 'LimitEnforceRate' | 'LimitTrackUsage' | 'LimitWarningAggregate' | 'LimitWarningCounter' | 'LimitWarningRate' | 'ProcessChunks' | 'ProcessExtraction' | 'ProcessFileEmbedding' | 'ProcessImageEmbedding' | 'ProcessImageVersions';
1206
1228
  /** Object form -- { $type, data } with typed parameters. */
1207
1229
  export type BlueprintNodeObject = {
1208
1230
  $type: 'AuthzAllowAll';
@@ -1216,9 +1238,6 @@ export type BlueprintNodeObject = {
1216
1238
  } | {
1217
1239
  $type: 'AuthzDenyAll';
1218
1240
  data?: Record<string, never>;
1219
- } | {
1220
- $type: 'AuthzFilePath';
1221
- data: AuthzFilePathParams;
1222
1241
  } | {
1223
1242
  $type: 'AuthzDirectOwner';
1224
1243
  data: AuthzDirectOwnerParams;
@@ -1228,18 +1247,21 @@ export type BlueprintNodeObject = {
1228
1247
  } | {
1229
1248
  $type: 'AuthzEntityMembership';
1230
1249
  data: AuthzEntityMembershipParams;
1250
+ } | {
1251
+ $type: 'AuthzFilePath';
1252
+ data: AuthzFilePathParams;
1231
1253
  } | {
1232
1254
  $type: 'AuthzMemberList';
1233
1255
  data: AuthzMemberListParams;
1256
+ } | {
1257
+ $type: 'AuthzMemberOwner';
1258
+ data: AuthzMemberOwnerParams;
1234
1259
  } | {
1235
1260
  $type: 'AuthzNotReadOnly';
1236
1261
  data: AuthzNotReadOnlyParams;
1237
1262
  } | {
1238
1263
  $type: 'AuthzOrgHierarchy';
1239
1264
  data: AuthzOrgHierarchyParams;
1240
- } | {
1241
- $type: 'AuthzMemberOwner';
1242
- data: AuthzMemberOwnerParams;
1243
1265
  } | {
1244
1266
  $type: 'AuthzPeerOwnership';
1245
1267
  data: AuthzPeerOwnershipParams;
@@ -1285,6 +1307,9 @@ export type BlueprintNodeObject = {
1285
1307
  } | {
1286
1308
  $type: 'DataForceCurrentUser';
1287
1309
  data: DataForceCurrentUserParams;
1310
+ } | {
1311
+ $type: 'DataI18n';
1312
+ data: DataI18nParams;
1288
1313
  } | {
1289
1314
  $type: 'DataId';
1290
1315
  data: DataIdParams;
@@ -537,6 +537,7 @@ function buildBlueprintStorageConfig() {
537
537
  t.tsLiteralType(t.stringLiteral('org'))
538
538
  ])), 'Storage scope. "app" (default) creates app-level storage (no owner_id). "org" creates per-org/user storage (owner_id = org entity id, buckets seeded per-entity via AFTER INSERT trigger). Only "app" and "org" are allowed — child entity types get storage via entity_types[].storage.'),
539
539
  addJSDoc(optionalProp('storage_key', t.tsStringKeyword()), 'Discriminator for multi-module storage. Defaults to "default" (omitted from table names). Non-default keys appear as an infix: {prefix}_{storage_key}_buckets. Max 16 chars, lowercase snake_case.'),
540
+ addJSDoc(optionalProp('prefix', t.tsStringKeyword()), 'Override the table-name prefix. By default the prefix is derived from the scope (e.g. "org"). Set to an empty string to produce unprefixed table names (e.g. "buckets" instead of "org_buckets").'),
540
541
  addJSDoc(optionalProp('buckets', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintBucketSeed')))), 'Initial bucket seed entries. Each creates a row in {prefix}_buckets during provisioning.'),
541
542
  addJSDoc(optionalProp('upload_url_expiry_seconds', t.tsNumberKeyword()), 'Override for presigned upload URL expiry time in seconds.'),
542
543
  addJSDoc(optionalProp('download_url_expiry_seconds', t.tsNumberKeyword()), 'Override for presigned download URL expiry time in seconds.'),
@@ -597,6 +598,7 @@ function buildBlueprintNamespaceConfig() {
597
598
  t.tsLiteralType(t.stringLiteral('org'))
598
599
  ])), '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.'),
599
600
  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.'),
601
+ addJSDoc(optionalProp('prefix', t.tsStringKeyword()), 'Override the table-name prefix. By default the prefix is derived from the scope (e.g. "org"). Set to an empty string to produce unprefixed table names (e.g. "namespaces" instead of "org_namespaces").'),
600
602
  addJSDoc(optionalProp('policies', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintPolicy')))), 'RLS policy overrides for the namespaces table. NULL = apply defaults from apply_namespace_security().'),
601
603
  addJSDoc(optionalProp('provisions', t.tsTypeLiteral([
602
604
  optionalProp('namespaces', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
@@ -617,6 +619,7 @@ function buildBlueprintFunctionConfig() {
617
619
  t.tsLiteralType(t.stringLiteral('org'))
618
620
  ])), '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.'),
619
621
  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.'),
622
+ addJSDoc(optionalProp('prefix', t.tsStringKeyword()), 'Override the table-name prefix. By default the prefix is derived from the scope (e.g. "org"). Set to an empty string to produce unprefixed table names (e.g. "function_definitions" instead of "org_function_definitions").'),
620
623
  addJSDoc(optionalProp('policies', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintPolicy')))), 'RLS policy overrides for the function tables. NULL = apply defaults from apply_function_security().'),
621
624
  addJSDoc(optionalProp('provisions', t.tsTypeLiteral([
622
625
  optionalProp('definitions', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
@@ -638,9 +641,12 @@ function buildBlueprintAgentConfig() {
638
641
  t.tsLiteralType(t.stringLiteral('org'))
639
642
  ])), '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.'),
640
643
  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.'),
644
+ addJSDoc(optionalProp('prefix', t.tsStringKeyword()), 'Override the table-name prefix. By default the prefix is derived from the scope (e.g. "org"). Set to an empty string to produce unprefixed table names (e.g. "agent_thread" instead of "org_agent_thread").'),
641
645
  addJSDoc(optionalProp('api_name', t.tsStringKeyword()), 'API name for the agent module. Used in GraphQL naming. Defaults to "agent".'),
642
- 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.'),
643
- addJSDoc(optionalProp('knowledge', t.tsTypeLiteral([
646
+ addJSDoc(optionalProp('has_plans', t.tsBooleanKeyword()), 'Whether to provision the agent_plan table for workflow plans with ordered tasks and approval gates. When true, tasks belong to plans (plan_id NOT NULL) instead of directly to threads. Defaults to false.'),
647
+ addJSDoc(optionalProp('has_resources', t.tsBooleanKeyword()), 'Whether to provision the unified agent_resource table (kind: skill/knowledge/convention) with auto-chunking (ProcessChunks) and vector embeddings. Defaults to false.'),
648
+ addJSDoc(optionalProp('has_agents', t.tsBooleanKeyword()), 'Whether to provision agent + agent_persona tables for agent registry and templates. Implies has_resources. Defaults to false.'),
649
+ addJSDoc(optionalProp('resources', t.tsArrayType(t.tsTypeLiteral([
644
650
  optionalProp('has_chunks', t.tsBooleanKeyword()),
645
651
  optionalProp('dimensions', t.tsNumberKeyword()),
646
652
  optionalProp('chunk_size', t.tsNumberKeyword()),
@@ -654,20 +660,23 @@ function buildBlueprintAgentConfig() {
654
660
  optionalProp('embedding_model', t.tsStringKeyword()),
655
661
  optionalProp('embedding_provider', t.tsStringKeyword()),
656
662
  optionalProp('search_indexes', t.tsArrayType(t.tsUnionType([
657
- t.tsLiteralType(t.stringLiteral('fulltext')),
663
+ t.tsLiteralType(t.stringLiteral('tsvector')),
658
664
  t.tsLiteralType(t.stringLiteral('bm25')),
659
665
  t.tsLiteralType(t.stringLiteral('trigram'))
660
666
  ])))
661
- ])), '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.'),
667
+ ]))), 'Resource configuration array. Controls vector dimensions, chunking strategy, embedding model/provider, and text search indexes for the agent_resource table. Set has_chunks to false to disable the ProcessChunks pipeline. Defaults: 768 dimensions, 1000 chunk_size, 200 chunk_overlap, paragraph strategy, ["tsvector"] search indexes.'),
662
668
  addJSDoc(optionalProp('policies', t.tsArrayType(t.tsTypeReference(t.identifier('BlueprintPolicy')))), 'RLS policy overrides for the agent tables. NULL = apply defaults from apply_agent_security().'),
663
669
  addJSDoc(optionalProp('provisions', t.tsTypeLiteral([
664
670
  optionalProp('thread', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
665
671
  optionalProp('message', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
666
672
  optionalProp('task', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
667
673
  optionalProp('prompt', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
668
- optionalProp('knowledge', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision')))
669
- ])), '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.')
670
- ]), '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).');
674
+ optionalProp('plan', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
675
+ optionalProp('resource', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
676
+ optionalProp('agent', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision'))),
677
+ optionalProp('persona', t.tsTypeReference(t.identifier('BlueprintEntityTableProvision')))
678
+ ])), 'Per-table overrides for agent tables. Each key targets a specific table (thread, message, task, prompt, plan, resource, agent, persona) and uses the same shape as table_provision: { nodes, fields, grants, use_rls, policies }. Fanned out to secure_table_provision.')
679
+ ]), '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. Opt-in: has_plans (plan + approval workflow), has_resources (unified skills/knowledge with chunking), has_agents (agent registry + personas, implies has_resources).');
671
680
  }
672
681
  /**
673
682
  * Build the BlueprintGraphConfig interface.
@@ -0,0 +1,2 @@
1
+ import type { NodeTypeDefinition } from '../types';
2
+ export declare const DataI18n: NodeTypeDefinition;
@@ -0,0 +1,44 @@
1
+ export const DataI18n = {
2
+ name: 'DataI18n',
3
+ slug: 'data_i18n',
4
+ category: 'data',
5
+ display_name: 'Internationalization',
6
+ description: 'Creates a companion _translations table with lang_code + translatable ' +
7
+ 'fields. Copies SELECT policies and column-ref fields from the base ' +
8
+ 'table. Adds @i18n smart comment so the Graphile i18n plugin discovers ' +
9
+ 'it. Requires i18n_module to be provisioned for the database.',
10
+ parameter_schema: {
11
+ type: 'object',
12
+ properties: {
13
+ fields: {
14
+ type: 'array',
15
+ items: {
16
+ type: 'string',
17
+ format: 'column-ref'
18
+ },
19
+ description: 'Field names on the base table to make translatable. Each field ' +
20
+ 'is duplicated on the translation table with the same type.'
21
+ },
22
+ table_suffix: {
23
+ type: 'string',
24
+ description: 'Suffix for the translation table name',
25
+ default: '_translations'
26
+ },
27
+ lang_code_type: {
28
+ type: 'string',
29
+ enum: ['citext', 'text'],
30
+ description: 'Type for the lang_code column',
31
+ default: 'citext'
32
+ },
33
+ copy_mutation_policies: {
34
+ type: 'boolean',
35
+ description: 'Whether to also copy INSERT/UPDATE/DELETE policies (not just ' +
36
+ 'SELECT). Default true — translations should be editable by the ' +
37
+ 'same users who can edit the base row.',
38
+ default: true
39
+ }
40
+ },
41
+ required: ['fields']
42
+ },
43
+ tags: ['i18n', 'translation', 'schema']
44
+ };
@@ -7,6 +7,7 @@ export { DataCompositeField } from './data-composite-field';
7
7
  export { DataDirectOwner } from './data-direct-owner';
8
8
  export { DataEntityMembership } from './data-entity-membership';
9
9
  export { DataForceCurrentUser } from './data-force-current-user';
10
+ export { DataI18n } from './data-i18n';
10
11
  export { DataId } from './data-id';
11
12
  export { DataImmutableFields } from './data-immutable-fields';
12
13
  export { DataInflection } from './data-inflection';
package/esm/data/index.js CHANGED
@@ -7,6 +7,7 @@ export { DataCompositeField } from './data-composite-field';
7
7
  export { DataDirectOwner } from './data-direct-owner';
8
8
  export { DataEntityMembership } from './data-entity-membership';
9
9
  export { DataForceCurrentUser } from './data-force-current-user';
10
+ export { DataI18n } from './data-i18n';
10
11
  export { DataId } from './data-id';
11
12
  export { DataImmutableFields } from './data-immutable-fields';
12
13
  export { DataInflection } from './data-inflection';
@@ -33,26 +33,18 @@ export const PresetAuthEmailMagic = {
33
33
  modules: [
34
34
  'users_module',
35
35
  'membership_types_module',
36
- 'permissions_module:app',
37
- 'limits_module:app',
38
- 'levels_module:app',
39
- 'memberships_module:app',
36
+ ['permissions_module', { scope: 'app' }],
37
+ ['limits_module', { scope: 'app' }],
38
+ ['levels_module', { scope: 'app' }],
39
+ ['memberships_module', { scope: 'app' }],
40
40
  'sessions_module',
41
41
  'user_state_module',
42
- 'config_secrets_user_module',
42
+ 'user_credentials_module',
43
+ 'config_secrets_module',
43
44
  'emails_module',
44
45
  'rls_module',
45
46
  'user_auth_module',
46
47
  'session_secrets_module'
47
48
  ],
48
- includes_notes: {
49
- session_secrets_module: 'Stores nonces for magic-link and email-OTP flows. Without it those procedures are not emitted.'
50
- },
51
- omits_notes: {
52
- rate_limits_module: 'Same reasoning as `auth:email` — add later via `auth:hardened`.',
53
- connected_accounts_module: 'No OAuth / SSO in this preset.',
54
- webauthn_credentials_module: 'No passkeys — add `auth:passkey`.',
55
- phone_numbers_module: 'No SMS — add `auth:hardened`.'
56
- },
57
49
  extends: ['auth:email']
58
50
  };
@@ -9,9 +9,9 @@ import type { ModulePreset } from './types';
9
9
  * `set_password`, `reset_password`, `forgot_password`, `verify_email`,
10
10
  * `delete_account`, `my_sessions`, API-key CRUD. Nothing more.
11
11
  *
12
- * Includes `permissions_module:app`, `limits_module:app`, and
13
- * `levels_module:app` because `memberships_module:app` has NOT NULL
14
- * foreign keys to the tables they create (grants, caps, levels).
12
+ * Includes permissions, limits, and levels modules (app scope) because
13
+ * the app-scoped memberships module has NOT NULL foreign keys to the
14
+ * tables they create (grants, caps, levels).
15
15
  *
16
16
  * It deliberately excludes rate limits, connected accounts / identity
17
17
  * providers (OAuth), WebAuthn (passkeys), phone numbers (SMS), invites,
@@ -8,9 +8,9 @@
8
8
  * `set_password`, `reset_password`, `forgot_password`, `verify_email`,
9
9
  * `delete_account`, `my_sessions`, API-key CRUD. Nothing more.
10
10
  *
11
- * Includes `permissions_module:app`, `limits_module:app`, and
12
- * `levels_module:app` because `memberships_module:app` has NOT NULL
13
- * foreign keys to the tables they create (grants, caps, levels).
11
+ * Includes permissions, limits, and levels modules (app scope) because
12
+ * the app-scoped memberships module has NOT NULL foreign keys to the
13
+ * tables they create (grants, caps, levels).
14
14
  *
15
15
  * It deliberately excludes rate limits, connected accounts / identity
16
16
  * providers (OAuth), WebAuthn (passkeys), phone numbers (SMS), invites,
@@ -44,35 +44,16 @@ export const PresetAuthEmail = {
44
44
  modules: [
45
45
  'users_module',
46
46
  'membership_types_module',
47
- 'permissions_module:app',
48
- 'limits_module:app',
49
- 'levels_module:app',
50
- 'memberships_module:app',
47
+ ['permissions_module', { scope: 'app' }],
48
+ ['limits_module', { scope: 'app' }],
49
+ ['levels_module', { scope: 'app' }],
50
+ ['memberships_module', { scope: 'app' }],
51
51
  'sessions_module',
52
52
  'user_state_module',
53
- 'config_secrets_user_module',
53
+ 'user_credentials_module',
54
+ 'config_secrets_module',
54
55
  'emails_module',
55
56
  'rls_module',
56
57
  'user_auth_module'
57
- ],
58
- includes_notes: {
59
- 'memberships_module:app': 'Required by `user_auth_module`: every user gets an app-level membership row at sign-up.',
60
- membership_types_module: "Required by `memberships_module:app`; defines the 'app' scope.",
61
- 'permissions_module:app': 'Required by `memberships_module:app`: NOT NULL FK to grants table.',
62
- 'limits_module:app': 'Required by `memberships_module:app`: NOT NULL FK to caps table.',
63
- 'levels_module:app': 'Required by `memberships_module:app`: NOT NULL FK to levels table.',
64
- emails_module: 'Required by the `user_auth_module` insert trigger (`RAISE EXCEPTION REQUIRES emails_module`).',
65
- config_secrets_user_module: 'Required for password hashing; referenced by `set_password`, `verify_password`, and reset flows.',
66
- user_state_module: 'API-key storage (`create_api_key`, `revoke_api_key`, `my_api_keys`).'
67
- },
68
- omits_notes: {
69
- rate_limits_module: 'Omitted intentionally; throttle_* helpers are null-safe and the auth procs compile without it. Add later via `auth:hardened`.',
70
- connected_accounts_module: 'No OAuth / SSO in this preset — add `auth:sso`.',
71
- identity_providers_module: 'No OAuth provider configs without connected_accounts.',
72
- webauthn_credentials_module: 'No passkeys — add `auth:passkey`.',
73
- phone_numbers_module: 'No SMS login — add `auth:hardened` or the SMS-only refactor path.',
74
- 'memberships_module:org': 'No org/team structure — move to `b2b` when you need one.',
75
- invites_module: 'Self-serve signup only.',
76
- session_secrets_module: 'No magic-link / email-OTP nonces; add `auth:email+magic`.'
77
- }
58
+ ]
78
59
  };
@@ -30,13 +30,14 @@ export const PresetAuthHardened = {
30
30
  modules: [
31
31
  'users_module',
32
32
  'membership_types_module',
33
- 'permissions_module:app',
34
- 'limits_module:app',
35
- 'levels_module:app',
36
- 'memberships_module:app',
33
+ ['permissions_module', { scope: 'app' }],
34
+ ['limits_module', { scope: 'app' }],
35
+ ['levels_module', { scope: 'app' }],
36
+ ['memberships_module', { scope: 'app' }],
37
37
  'sessions_module',
38
38
  'user_state_module',
39
- 'config_secrets_user_module',
39
+ 'user_credentials_module',
40
+ 'config_secrets_module',
40
41
  'emails_module',
41
42
  'rls_module',
42
43
  'user_auth_module',
@@ -49,21 +50,5 @@ export const PresetAuthHardened = {
49
50
  'phone_numbers_module',
50
51
  'devices_module'
51
52
  ],
52
- includes_notes: {
53
- rate_limits_module: 'Throttling for sign-in, password reset, sign-up, and IP-based gates.',
54
- connected_accounts_module: 'OAuth / SSO linkage.',
55
- identity_providers_module: 'OAuth provider configs (required for `connected_accounts_module`).',
56
- webauthn_credentials_module: 'Per-user passkey storage.',
57
- webauthn_auth_module: 'Passkey challenge + assertion runtime.',
58
- session_secrets_module: 'Nonces for magic links, email OTP, and WebAuthn challenges.',
59
- phone_numbers_module: 'SMS sign-in / MFA support.',
60
- devices_module: 'Device tracking and trusted-device MFA bypass.'
61
- },
62
- omits_notes: {
63
- 'memberships_module:org': 'No orgs / teams — use `b2b` when you need multi-tenancy.',
64
- invites_module: 'No invite flow — add via `b2b`.',
65
- storage_module: 'Add separately if you need file uploads.',
66
- crypto_addresses_module: 'Not a web3 preset; omit unless doing wallet sign-in.'
67
- },
68
53
  extends: ['auth:email', 'auth:email+magic', 'auth:sso', 'auth:passkey']
69
54
  };
@@ -31,13 +31,14 @@ export const PresetAuthPasskey = {
31
31
  modules: [
32
32
  'users_module',
33
33
  'membership_types_module',
34
- 'permissions_module:app',
35
- 'limits_module:app',
36
- 'levels_module:app',
37
- 'memberships_module:app',
34
+ ['permissions_module', { scope: 'app' }],
35
+ ['limits_module', { scope: 'app' }],
36
+ ['levels_module', { scope: 'app' }],
37
+ ['memberships_module', { scope: 'app' }],
38
38
  'sessions_module',
39
39
  'user_state_module',
40
- 'config_secrets_user_module',
40
+ 'user_credentials_module',
41
+ 'config_secrets_module',
41
42
  'emails_module',
42
43
  'rls_module',
43
44
  'user_auth_module',
@@ -45,15 +46,5 @@ export const PresetAuthPasskey = {
45
46
  'webauthn_credentials_module',
46
47
  'webauthn_auth_module'
47
48
  ],
48
- includes_notes: {
49
- webauthn_credentials_module: 'Per-user WebAuthn credential storage. Without it, passkey registration does not compile.',
50
- webauthn_auth_module: 'Runtime challenge + assertion flow.',
51
- session_secrets_module: 'Challenge nonces for registration and assertion.'
52
- },
53
- omits_notes: {
54
- rate_limits_module: 'Add via `auth:hardened` for production.',
55
- connected_accounts_module: 'No OAuth / SSO — add via `auth:hardened`.',
56
- phone_numbers_module: 'No SMS.'
57
- },
58
49
  extends: ['auth:email']
59
50
  };
@@ -6,7 +6,7 @@ import type { ModulePreset } from './types';
6
6
  * `(provider, external_id)`) and `identity_providers_module` (the provider
7
7
  * config: URLs, client_id, encrypted client_secret, scopes, PKCE/nonce
8
8
  * knobs). The generator then emits `sign_in_identity` / `sign_up_identity`
9
- * procedures which rely on `config_secrets_user_module` to decrypt the client
9
+ * procedures which rely on `config_secrets_module` to decrypt the client
10
10
  * secret at auth time.
11
11
  *
12
12
  * Password fallback stays on by default (break-glass for admins); flip the
@@ -5,7 +5,7 @@
5
5
  * `(provider, external_id)`) and `identity_providers_module` (the provider
6
6
  * config: URLs, client_id, encrypted client_secret, scopes, PKCE/nonce
7
7
  * knobs). The generator then emits `sign_in_identity` / `sign_up_identity`
8
- * procedures which rely on `config_secrets_user_module` to decrypt the client
8
+ * procedures which rely on `config_secrets_module` to decrypt the client
9
9
  * secret at auth time.
10
10
  *
11
11
  * Password fallback stays on by default (break-glass for admins); flip the
@@ -26,7 +26,7 @@ export const PresetAuthSso = {
26
26
  'encrypted client secrets) and `connected_accounts_module` (the junction mapping a ' +
27
27
  'Constructive user to a `(provider, external_id)` pair). The generator emits ' +
28
28
  '`sign_in_identity` and `sign_up_identity` procedures which decrypt the client secret ' +
29
- 'through `config_secrets_user_module` at auth time. Keep password flows as break-glass, or ' +
29
+ 'through `config_secrets_module` at auth time. Keep password flows as break-glass, or ' +
30
30
  'disable them via `app_settings_auth` toggles for strictly-SSO deployments.',
31
31
  good_for: [
32
32
  'B2B apps where end users sign in via their employer IdP',
@@ -40,29 +40,19 @@ export const PresetAuthSso = {
40
40
  modules: [
41
41
  'users_module',
42
42
  'membership_types_module',
43
- 'permissions_module:app',
44
- 'limits_module:app',
45
- 'levels_module:app',
46
- 'memberships_module:app',
43
+ ['permissions_module', { scope: 'app' }],
44
+ ['limits_module', { scope: 'app' }],
45
+ ['levels_module', { scope: 'app' }],
46
+ ['memberships_module', { scope: 'app' }],
47
47
  'sessions_module',
48
48
  'user_state_module',
49
- 'config_secrets_user_module',
49
+ 'user_credentials_module',
50
+ 'config_secrets_module',
50
51
  'emails_module',
51
52
  'rls_module',
52
53
  'user_auth_module',
53
54
  'connected_accounts_module',
54
55
  'identity_providers_module'
55
56
  ],
56
- includes_notes: {
57
- connected_accounts_module: 'Junction table for (user, provider, external_id). Without it, `sign_in_identity` does not compile.',
58
- identity_providers_module: 'Provider config table (URLs, client_id, encrypted client_secret, scopes, PKCE knobs).',
59
- config_secrets_user_module: 'Required by `auth:email` already; also used by SSO to decrypt the provider client_secret at auth time.'
60
- },
61
- omits_notes: {
62
- webauthn_credentials_module: 'No passkeys — add `auth:passkey` or move to `auth:hardened`.',
63
- rate_limits_module: 'Omitted; add via `auth:hardened` for production.',
64
- session_secrets_module: "Not required for authorization-code OAuth; add if you also want magic-link flows. PKCE doesn't require it for stateless OAuth flows today.",
65
- phone_numbers_module: 'No SMS in this preset.'
66
- },
67
57
  extends: ['auth:email']
68
58
  };