docs: add constructive-membership-types skill for dynamic entity provisioning#85
Conversation
…nition format with membership_types
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| policies: [ | ||
| { | ||
| $type: 'AuthzEntityMembership', | ||
| data: { entity_field: 'channel_id', membership_type: 3 }, |
There was a problem hiding this comment.
maybe we should consider entity_type: 'channel'
There was a problem hiding this comment.
Good call — membership_type: 3 is fragile since the number depends on provisioning order. entity_type: 'channel' would let the policy resolve the membership type by prefix at construction time, same way parent_entity: 'org' resolves in Phase 0.
This would mean construct_blueprint() Phase 1 (tables) would need to resolve entity_type string → membership_type int when processing policy nodes. The membership_types are already in the table_map by then, so the lookup data is available.
I'll update the examples in this skill doc to use entity_type: 'channel' to reflect the intended API. The actual resolution logic would be part of the construct_blueprint() changes in the DB PR.
Want me to also create an issue tracking the entity_type string resolution in construct_blueprint()?
| hasLimits: false, | ||
| hasProfiles: false, | ||
| hasLevels: false, | ||
| skipEntityPolicies: false, |
There was a problem hiding this comment.
I don't see why we just don't leverage the functionality that we've encapsulated for secure table provision here. Maybe there is a way to make it simple.
There was a problem hiding this comment.
That's a good point. Right now entity_type_provision calls provision_membership_table() which internally calls secure_table_provision for the entity table, then layers on the membership-specific modules (permissions, memberships, security policies). The skipEntityPolicies flag skips the RLS policies that provision_membership_table would normally create on the entity table.
The question is whether we could instead express this through the existing secure_table_provision config — e.g. pass policy options through to it rather than having a separate skipEntityPolicies boolean on the provisioning API.
Two approaches:
-
Keep
entity_type_provisionas a high-level wrapper that encapsulates thesecure_table_provisioncall internally — simpler API for the common case, but theskip*flags feel like leaky abstractions from the internals. -
Expose the
secure_table_provisionoptions directly — let the caller pass atableProvisionOptionsobject that gets forwarded tosecure_table_provision. More flexible, and reuses the vocabulary developers already know from table provisioning.
Option 2 feels cleaner — the entity provisioner handles membership-specific concerns (permissions table, memberships module, types registration) and delegates table-level concerns to secure_table_provision with whatever options the caller provides. The skipEntityPolicies flag would go away in favor of the standard table provision config.
Want me to update the doc to reflect option 2, or should we flesh this out more in a planning issue first?
… in policy examples
Explain that membership-based policies support entity_type prefix strings as an alternative to hardcoded membership_type integers.
Summary
Adds a new
constructive-membership-typesskill documenting dynamic entity type provisioning and membership types using the GraphQL ORM / CLI syntax. This is the public-facing counterpart to the SQL-focusedentity-types-and-provisioningskill inconstructive-db.New skill (
.agents/skills/constructive-membership-types/):SKILL.md— Overview of the entity type hierarchy (app=1, org=2, dynamic=3+), permission model per level, parent-child relationships, and three provisioning methods (blueprint, ORM, CLI)references/orm-provisioning.md—entityTypeProvisiontrigger table usage, field reference, output fields, nested provisioning, andprovisionMembershipTable()lower-level functionreferences/blueprint-membership-types.md—membership_types[]array spec in blueprint definitions,BlueprintMembershipTypefield reference, TypeScript type examples, nested types, and combining with tables/relationsUpdated existing skill (
.agents/skills/constructive/):SKILL.md— Updated blueprint description line to mentionmembership_types[](Phase 0)references/blueprint-definition-format.md— Addedmembership_typesto the top-level JSON structure and a new "Membership Types (Phase 0)" section with field reference table and processing notesRelated: constructive-db PR #813 (SQL-level naming cleanup + private skill), constructive PR #983 (node_type_registry updates, merged)
Updates since last revision
entity_typestring instead of hardcodedmembership_typeint: AllAuthzEntityMembershippolicy examples now useentity_type: 'channel'(prefix string) instead ofmembership_type: 3(fragile integer).constructBlueprint()resolves the prefix to the correct type ID at construction time. This applies to the TypeScript type example, ORM blueprint example, and JSON combining example inblueprint-membership-types.md.Review & Testing Checklist for Human
entity_typestring resolution (design-ahead): The doc now showsentity_type: 'channel'in policy nodes, but this resolution logic (prefix → membership_type int) may not yet be implemented inconstruct_blueprint(). Verify the DB-side implementation supports this or track it as a follow-up.skipEntityPoliciesvssecure_table_provisiondelegation: There's an open discussion on this PR about whetherskipEntityPoliciesshould be replaced by forwarding options tosecure_table_provisiondirectly. If the API changes, the doc will need updating.databaseId,parentEntity,outMembershipType, etc.) match the actual generated SDK from@constructive-io/node-type-registry. These were inferred from code patterns, not tested against a running instance.constructive public:entity-type-provision createandconstructive public:membership-type listmatch the actual CLI tool output (runconstructive public:entity-type-provision --helpto check).BlueprintMembershipTypeinterface fields (parent_entity,skip_entity_policies,has_limits, etc.) match the actual TypeScript interface innode-type-registry.Notes
AGENTS.md:SKILL.mdrouter +references/subdirectory with focused topic docs..agents/skills/documentation.Link to Devin session: https://app.devin.ai/sessions/61be2d8e471048e294178e4a95d7e9dc
Requested by: @pyramation