Skip to content

feat(node-type-registry): add module presets#1015

Merged
pyramation merged 1 commit intomainfrom
feat/module-presets
Apr 20, 2026
Merged

feat(node-type-registry): add module presets#1015
pyramation merged 1 commit intomainfrom
feat/module-presets

Conversation

@pyramation
Copy link
Copy Markdown
Contributor

Summary

Ships eight curated Constructive module presets as TypeScript metadata in the node-type-registry package. Presets are documented shapes for provision_database_modules(v_modules => ...) — they tell a user which modules to install for a recognizable app shape (internal tool, consumer email login, SSO, B2B SaaS, …) and why each module is or isn't included.

New package export: graphql/node-type-registry/src/module-presets/

import { allModulePresets, getModulePreset, PresetAuthEmail } from '@constructive-io/node-type-registry';

getModulePreset('auth:email').modules;
// ['users_module', 'membership_types_module', 'memberships_module:app',
//  'sessions_module', 'secrets_module', 'encrypted_secrets_module',
//  'emails_module', 'rls_module', 'user_auth_module']

Presets

Name Shape
minimal users + sessions + rls + secrets. No auth procs. Upstream handles identity.
auth:email Email + password. Single tenant. No SSO / passkey / SMS / rate limits.
auth:email+magic auth:email + magic-link / email-OTP nonces.
auth:sso auth:email + OAuth providers and connected accounts.
auth:passkey auth:email + WebAuthn.
auth:hardened Rate limits + SSO + passkeys + SMS + magic links. Single tenant.
b2b auth:hardened + orgs + invites + permissions + levels + profiles + hierarchy.
full Equivalent to the current default ['all'].

Shape

interface ModulePreset {
  name: string;
  display_name: string;
  summary: string;
  description: string;
  good_for: string[];
  not_for: string[];
  modules: string[];
  includes_notes?: Record<string, string>;
  omits_notes?: Record<string, string>;
  extends?: string[];
}

Each preset file has a top-level JSDoc narrative plus per-module includes_notes / omits_notes rationale, so CLIs / docs / --explain output all have a single source of truth.

Presets live alongside node types (authz/, data/, relation/, view/) in the registry package, but are a sibling concept — not NodeTypeDefinitions. Node types are reusable blueprint building blocks; presets are starting points for which modules to install before any blueprint is authored.

Follow-up scope explicitly not in this PR: feature-flag / toggle-inside-preset syntax (e.g. settings?: { app_settings_auth: { allow_password_sign_up: false } }). The ModulePreset shape leaves room to add that later non-breakingly. Source doc with the preset rationale lives in constructive-db docs/architecture/module-presets.md.

Review & Testing Checklist for Human

  • Confirm preset names and contents match what you want published (minimal, auth:email, auth:email+magic, auth:sso, auth:passkey, auth:hardened, b2b, full).
  • Sanity-check the per-preset includes_notes / omits_notes narratives — they're the user-facing reasoning and should match your mental model.
  • Verify placement under graphql/node-type-registry/src/module-presets/ is the right home. Alternative: a new package (@constructive-io/module-presets) or pgpm/export/src/. Easy to move if you'd prefer.

Notes

Known caveat: every auth preset currently includes emails_module because the user_auth_module insert trigger in constructive-db hard-raises REQUIRES (emails_module). Pure SSO-only / SMS-only / passkey-only (no emails) needs that trigger loosened — called out as a refactor target in the constructive-db docs. For now, presets reflect what provisioning will actually accept today.

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

Ships eight curated Constructive module presets as TypeScript metadata in
the node-type-registry package: minimal, auth:email, auth:email+magic,
auth:sso, auth:passkey, auth:hardened, b2b, full.

Each preset is a ModulePreset record with a display_name, a summary, a
narrative description, good_for / not_for scenarios, a flat module list,
and per-module includes_notes / omits_notes explaining the choices. This
is metadata only — passing preset.modules to provision_database_modules
is what actually installs them.

Exposed via allModulePresets and getModulePreset(name).
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 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

@pyramation pyramation merged commit 2ed5014 into main Apr 20, 2026
51 checks passed
@pyramation pyramation deleted the feat/module-presets branch April 20, 2026 06:32
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