Skip to content

Commit 568c176

Browse files
authored
Merge pull request #983 from constructive-io/devin/1776329885-node-type-registry-naming
feat: update authz descriptions + add BlueprintMembershipType for dynamic entity types
2 parents edc52fa + c99433d commit 568c176

7 files changed

Lines changed: 93 additions & 10 deletions

graphql/node-type-registry/src/authz/authz-entity-membership.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const AuthzEntityMembership: NodeTypeDefinition = {
1818
"integer",
1919
"string"
2020
],
21-
"description": "Scope: 1=app, 2=org, 3=group (or string name resolved via membership_types_module)"
21+
"description": "Scope: 1=app, 2=org, 3+=dynamic entity types (or string name resolved via membership_types_module)"
2222
},
2323
"permission": {
2424
"type": "string",

graphql/node-type-registry/src/authz/authz-membership-check.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const AuthzMembership: NodeTypeDefinition = {
1414
"integer",
1515
"string"
1616
],
17-
"description": "Scope: 1=app, 2=org, 3=group (or string name resolved via membership_types_module)"
17+
"description": "Scope: 1=app, 2=org, 3+=dynamic entity types (or string name resolved via membership_types_module)"
1818
},
1919
"permission": {
2020
"type": "string",

graphql/node-type-registry/src/authz/authz-peer-ownership.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const AuthzPeerOwnership: NodeTypeDefinition = {
1818
"integer",
1919
"string"
2020
],
21-
"description": "Scope: 1=app, 2=org, 3=group (or string name resolved via membership_types_module)"
21+
"description": "Scope: 1=app, 2=org, 3+=dynamic entity types (or string name resolved via membership_types_module)"
2222
},
2323
"permission": {
2424
"type": "string",

graphql/node-type-registry/src/authz/authz-related-entity-membership.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const AuthzRelatedEntityMembership: NodeTypeDefinition = {
1818
"integer",
1919
"string"
2020
],
21-
"description": "Scope: 1=app, 2=org, 3=group (or string name resolved via membership_types_module)"
21+
"description": "Scope: 1=app, 2=org, 3+=dynamic entity types (or string name resolved via membership_types_module)"
2222
},
2323
"obj_table_id": {
2424
"type": "string",

graphql/node-type-registry/src/authz/authz-related-peer-ownership.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const AuthzRelatedPeerOwnership: NodeTypeDefinition = {
1818
"integer",
1919
"string"
2020
],
21-
"description": "Scope: 1=app, 2=org, 3=group (or string name resolved via membership_types_module)"
21+
"description": "Scope: 1=app, 2=org, 3+=dynamic entity types (or string name resolved via membership_types_module)"
2222
},
2323
"obj_table_id": {
2424
"type": "string",

graphql/node-type-registry/src/blueprint-types.generated.ts

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ export interface AuthzDirectOwnerAnyParams {
372372
}
373373
/** Membership check that verifies the user has membership (optionally with specific permission) without binding to any entity from the row. Uses EXISTS subquery against SPRT table. */
374374
export interface AuthzMembershipParams {
375-
/* Scope: 1=app, 2=org, 3=group (or string name resolved via membership_types_module) */
375+
/* Scope: 1=app, 2=org, 3+=dynamic entity types (or string name resolved via membership_types_module) */
376376
membership_type: number | string;
377377
/* Single permission name to check (resolved to bitstring mask) */
378378
permission?: string;
@@ -387,7 +387,7 @@ export interface AuthzMembershipParams {
387387
export interface AuthzEntityMembershipParams {
388388
/* Column name referencing the entity (e.g., entity_id, org_id) */
389389
entity_field: string;
390-
/* Scope: 1=app, 2=org, 3=group (or string name resolved via membership_types_module) */
390+
/* Scope: 1=app, 2=org, 3+=dynamic entity types (or string name resolved via membership_types_module) */
391391
membership_type?: number | string;
392392
/* Single permission name to check (resolved to bitstring mask) */
393393
permission?: string;
@@ -402,7 +402,7 @@ export interface AuthzEntityMembershipParams {
402402
export interface AuthzRelatedEntityMembershipParams {
403403
/* Column name on protected table referencing the join table */
404404
entity_field: string;
405-
/* Scope: 1=app, 2=org, 3=group (or string name resolved via membership_types_module) */
405+
/* Scope: 1=app, 2=org, 3+=dynamic entity types (or string name resolved via membership_types_module) */
406406
membership_type?: number | string;
407407
/* UUID of the join table (alternative to obj_schema/obj_table) */
408408
obj_table_id?: string;
@@ -490,7 +490,7 @@ export interface AuthzCompositeParams {
490490
export interface AuthzPeerOwnershipParams {
491491
/* Column name on protected table referencing the owning user (e.g., owner_id) */
492492
owner_field: string;
493-
/* Scope: 1=app, 2=org, 3=group (or string name resolved via membership_types_module) */
493+
/* Scope: 1=app, 2=org, 3+=dynamic entity types (or string name resolved via membership_types_module) */
494494
membership_type?: number | string;
495495
/* Single permission name to check on the current user membership (resolved to bitstring mask) */
496496
permission?: string;
@@ -505,7 +505,7 @@ export interface AuthzPeerOwnershipParams {
505505
export interface AuthzRelatedPeerOwnershipParams {
506506
/* Column name on protected table referencing the related table (e.g., message_id) */
507507
entity_field: string;
508-
/* Scope: 1=app, 2=org, 3=group (or string name resolved via membership_types_module) */
508+
/* Scope: 1=app, 2=org, 3+=dynamic entity types (or string name resolved via membership_types_module) */
509509
membership_type?: number | string;
510510
/* UUID of the related table (alternative to obj_schema/obj_table) */
511511
obj_table_id?: string;
@@ -796,6 +796,29 @@ export interface BlueprintTableUniqueConstraint {
796796
/** Optional schema name override. */
797797
schema_name?: string;
798798
}
799+
/** A membership type entry for Phase 0 of construct_blueprint(). Provisions a full entity type with its own entity table, membership modules, and security policies via entity_type_provision. */
800+
export interface BlueprintMembershipType {
801+
/** Entity type name (e.g., "data_room", "channel", "department"). Must be unique per database. */
802+
name: string;
803+
/** Short prefix for generated objects (e.g., "dr", "ch", "dept"). Used in table/trigger naming. */
804+
prefix: string;
805+
/** Human-readable description of this entity type. */
806+
description?: string;
807+
/** Parent entity type name. Defaults to "org". */
808+
parent_entity?: string;
809+
/** Custom table name for the entity table. Defaults to name-derived convention. */
810+
table_name?: string;
811+
/** Whether this entity type is visible in the API. Defaults to true. */
812+
is_visible?: boolean;
813+
/** Whether to provision a limits module for this entity type. Defaults to false. */
814+
has_limits?: boolean;
815+
/** Whether to provision a profiles module for this entity type. Defaults to false. */
816+
has_profiles?: boolean;
817+
/** Whether to provision a levels module for this entity type. Defaults to false. */
818+
has_levels?: boolean;
819+
/** Whether to skip creating default RLS policies on the entity table. Defaults to false. */
820+
skip_entity_policies?: boolean;
821+
}
799822
/**
800823
* ===========================================================================
801824
* Node types -- discriminated union for nodes[] entries
@@ -1015,4 +1038,6 @@ export interface BlueprintDefinition {
10151038
full_text_searches?: BlueprintFullTextSearch[];
10161039
/** Unique constraints on table columns. */
10171040
unique_constraints?: BlueprintUniqueConstraint[];
1041+
/** Entity types to provision in Phase 0 (before tables). Each entry creates an entity table with membership modules and security. */
1042+
membership_types?: BlueprintMembershipType[];
10181043
}

graphql/node-type-registry/src/codegen/generate-types.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,54 @@ function buildBlueprintTableUniqueConstraint(): t.ExportNamedDeclaration {
599599
);
600600
}
601601

602+
function buildBlueprintMembershipType(): t.ExportNamedDeclaration {
603+
return addJSDoc(
604+
exportInterface('BlueprintMembershipType', [
605+
addJSDoc(
606+
requiredProp('name', t.tsStringKeyword()),
607+
'Entity type name (e.g., "data_room", "channel", "department"). Must be unique per database.'
608+
),
609+
addJSDoc(
610+
requiredProp('prefix', t.tsStringKeyword()),
611+
'Short prefix for generated objects (e.g., "dr", "ch", "dept"). Used in table/trigger naming.'
612+
),
613+
addJSDoc(
614+
optionalProp('description', t.tsStringKeyword()),
615+
'Human-readable description of this entity type.'
616+
),
617+
addJSDoc(
618+
optionalProp('parent_entity', t.tsStringKeyword()),
619+
'Parent entity type name. Defaults to "org".'
620+
),
621+
addJSDoc(
622+
optionalProp('table_name', t.tsStringKeyword()),
623+
'Custom table name for the entity table. Defaults to name-derived convention.'
624+
),
625+
addJSDoc(
626+
optionalProp('is_visible', t.tsBooleanKeyword()),
627+
'Whether this entity type is visible in the API. Defaults to true.'
628+
),
629+
addJSDoc(
630+
optionalProp('has_limits', t.tsBooleanKeyword()),
631+
'Whether to provision a limits module for this entity type. Defaults to false.'
632+
),
633+
addJSDoc(
634+
optionalProp('has_profiles', t.tsBooleanKeyword()),
635+
'Whether to provision a profiles module for this entity type. Defaults to false.'
636+
),
637+
addJSDoc(
638+
optionalProp('has_levels', t.tsBooleanKeyword()),
639+
'Whether to provision a levels module for this entity type. Defaults to false.'
640+
),
641+
addJSDoc(
642+
optionalProp('skip_entity_policies', t.tsBooleanKeyword()),
643+
'Whether to skip creating default RLS policies on the entity table. Defaults to false.'
644+
),
645+
]),
646+
'A membership type entry for Phase 0 of construct_blueprint(). Provisions a full entity type with its own entity table, membership modules, and security policies via entity_type_provision.'
647+
);
648+
}
649+
602650
function buildBlueprintTable(): t.ExportNamedDeclaration {
603651
return addJSDoc(
604652
exportInterface('BlueprintTable', [
@@ -711,6 +759,15 @@ function buildBlueprintDefinition(): t.ExportNamedDeclaration {
711759
),
712760
'Unique constraints on table columns.'
713761
),
762+
addJSDoc(
763+
optionalProp(
764+
'membership_types',
765+
t.tsArrayType(
766+
t.tsTypeReference(t.identifier('BlueprintMembershipType'))
767+
)
768+
),
769+
'Entity types to provision in Phase 0 (before tables). Each entry creates an entity table with membership modules and security.'
770+
),
714771
]),
715772
'The complete blueprint definition -- the JSONB shape accepted by construct_blueprint().'
716773
);
@@ -782,6 +839,7 @@ function buildProgram(meta?: MetaTableInfo[]): string {
782839
statements.push(buildBlueprintTableIndex());
783840
statements.push(buildBlueprintUniqueConstraint());
784841
statements.push(buildBlueprintTableUniqueConstraint());
842+
statements.push(buildBlueprintMembershipType());
785843

786844
// -- Node types discriminated union --
787845
statements.push(

0 commit comments

Comments
 (0)