Skip to content

docs: add constructive-membership-types skill for dynamic entity provisioning#85

Merged
pyramation merged 3 commits intomainfrom
devin/1776333417-membership-types-skill
Apr 16, 2026
Merged

docs: add constructive-membership-types skill for dynamic entity provisioning#85
pyramation merged 3 commits intomainfrom
devin/1776333417-membership-types-skill

Conversation

@pyramation
Copy link
Copy Markdown
Contributor

@pyramation pyramation commented Apr 16, 2026

Summary

Adds a new constructive-membership-types skill documenting dynamic entity type provisioning and membership types using the GraphQL ORM / CLI syntax. This is the public-facing counterpart to the SQL-focused entity-types-and-provisioning skill in constructive-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.mdentityTypeProvision trigger table usage, field reference, output fields, nested provisioning, and provisionMembershipTable() lower-level function
  • references/blueprint-membership-types.mdmembership_types[] array spec in blueprint definitions, BlueprintMembershipType field reference, TypeScript type examples, nested types, and combining with tables/relations

Updated existing skill (.agents/skills/constructive/):

  • SKILL.md — Updated blueprint description line to mention membership_types[] (Phase 0)
  • references/blueprint-definition-format.md — Added membership_types to the top-level JSON structure and a new "Membership Types (Phase 0)" section with field reference table and processing notes

Related: constructive-db PR #813 (SQL-level naming cleanup + private skill), constructive PR #983 (node_type_registry updates, merged)

Updates since last revision

  • entity_type string instead of hardcoded membership_type int: All AuthzEntityMembership policy examples now use entity_type: 'channel' (prefix string) instead of membership_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 in blueprint-membership-types.md.

Review & Testing Checklist for Human

  • entity_type string resolution (design-ahead): The doc now shows entity_type: 'channel' in policy nodes, but this resolution logic (prefix → membership_type int) may not yet be implemented in construct_blueprint(). Verify the DB-side implementation supports this or track it as a follow-up.
  • skipEntityPolicies vs secure_table_provision delegation: There's an open discussion on this PR about whether skipEntityPolicies should be replaced by forwarding options to secure_table_provision directly. If the API changes, the doc will need updating.
  • ORM field name accuracy: Verify camelCase ORM fields (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.
  • CLI command syntax: Confirm constructive public:entity-type-provision create and constructive public:membership-type list match the actual CLI tool output (run constructive public:entity-type-provision --help to check).
  • Blueprint definition field names: Verify BlueprintMembershipType interface fields (parent_entity, skip_entity_policies, has_limits, etc.) match the actual TypeScript interface in node-type-registry.

Notes

  • All examples use "Channel" / "channel" consistently (not "Data Room" / "data_room") per the naming convention established in the related PRs.
  • The skill follows the standard structure from AGENTS.md: SKILL.md router + references/ subdirectory with focused topic docs.
  • No code changes — this is purely .agents/skills/ documentation.

Link to Devin session: https://app.devin.ai/sessions/61be2d8e471048e294178e4a95d7e9dc
Requested by: @pyramation

@devin-ai-integration
Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

policies: [
{
$type: 'AuthzEntityMembership',
data: { entity_field: 'channel_id', membership_type: 3 },
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should consider entity_type: 'channel'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. Keep entity_type_provision as a high-level wrapper that encapsulates the secure_table_provision call internally — simpler API for the common case, but the skip* flags feel like leaky abstractions from the internals.

  2. Expose the secure_table_provision options directly — let the caller pass a tableProvisionOptions object that gets forwarded to secure_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?

Explain that membership-based policies support entity_type prefix
strings as an alternative to hardcoded membership_type integers.
@pyramation pyramation merged commit 394babb into main Apr 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant