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.
- package/README.md +4 -0
- package/blueprint-types.generated.d.ts +62 -37
- package/codegen/generate-types.js +16 -7
- package/data/data-i18n.d.ts +2 -0
- package/data/data-i18n.js +47 -0
- package/data/index.d.ts +1 -0
- package/data/index.js +3 -1
- package/esm/blueprint-types.generated.d.ts +62 -37
- package/esm/codegen/generate-types.js +16 -7
- package/esm/data/data-i18n.d.ts +2 -0
- package/esm/data/data-i18n.js +44 -0
- package/esm/data/index.d.ts +1 -0
- package/esm/data/index.js +1 -0
- package/esm/module-presets/auth-email-magic.js +6 -14
- package/esm/module-presets/auth-email.d.ts +3 -3
- package/esm/module-presets/auth-email.js +10 -29
- package/esm/module-presets/auth-hardened.js +6 -21
- package/esm/module-presets/auth-passkey.js +6 -15
- package/esm/module-presets/auth-sso.d.ts +1 -1
- package/esm/module-presets/auth-sso.js +8 -18
- package/esm/module-presets/b2b-storage.js +16 -22
- package/esm/module-presets/b2b.js +20 -38
- package/esm/module-presets/full.d.ts +1 -1
- package/esm/module-presets/full.js +25 -28
- package/esm/module-presets/minimal.js +1 -12
- package/esm/module-presets/types.d.ts +9 -15
- package/module-presets/auth-email-magic.js +6 -14
- package/module-presets/auth-email.d.ts +3 -3
- package/module-presets/auth-email.js +10 -29
- package/module-presets/auth-hardened.js +6 -21
- package/module-presets/auth-passkey.js +6 -15
- package/module-presets/auth-sso.d.ts +1 -1
- package/module-presets/auth-sso.js +8 -18
- package/module-presets/b2b-storage.js +16 -22
- package/module-presets/b2b.js +20 -38
- package/module-presets/full.d.ts +1 -1
- package/module-presets/full.js +25 -28
- package/module-presets/minimal.js +1 -12
- package/module-presets/types.d.ts +9 -15
- 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' | '
|
|
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 (
|
|
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
|
|
1119
|
-
|
|
1120
|
-
/**
|
|
1121
|
-
|
|
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?: ('
|
|
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,
|
|
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
|
-
|
|
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' | '
|
|
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('
|
|
643
|
-
addJSDoc(optionalProp('
|
|
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('
|
|
663
|
+
t.tsLiteralType(t.stringLiteral('tsvector')),
|
|
658
664
|
t.tsLiteralType(t.stringLiteral('bm25')),
|
|
659
665
|
t.tsLiteralType(t.stringLiteral('trigram'))
|
|
660
666
|
])))
|
|
661
|
-
])), '
|
|
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('
|
|
669
|
-
|
|
670
|
-
|
|
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,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
|
+
};
|
package/esm/data/index.d.ts
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';
|
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
|
-
'
|
|
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
|
|
13
|
-
*
|
|
14
|
-
*
|
|
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
|
|
12
|
-
*
|
|
13
|
-
*
|
|
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
|
-
'
|
|
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
|
-
'
|
|
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
|
-
'
|
|
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 `
|
|
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 `
|
|
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 `
|
|
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
|
-
'
|
|
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
|
};
|