diff --git a/agentic/pi/__tests__/provision-modules.test.ts b/agentic/pi/__tests__/provision-modules.test.ts index 0421b81db..de47bcbfe 100644 --- a/agentic/pi/__tests__/provision-modules.test.ts +++ b/agentic/pi/__tests__/provision-modules.test.ts @@ -26,7 +26,7 @@ describe('resolveProvisionModules', () => { }); it('selects a named preset via the last layer that sets one', () => { - const full = resolveProvisionModules([{ preset: 'b2b' }, { preset: 'full' }]); + const full = resolveProvisionModules([{ preset: 'auth:hardened' }, { preset: 'full' }]); expect(full).toEqual(getModulePreset('full')!.modules); }); diff --git a/packages/node-type-registry/__tests__/module-types.test.ts b/packages/node-type-registry/__tests__/module-types.test.ts index 3d82687ae..0b06ee88e 100644 --- a/packages/node-type-registry/__tests__/module-types.test.ts +++ b/packages/node-type-registry/__tests__/module-types.test.ts @@ -156,17 +156,47 @@ describe('module type registry', () => { test('registers the complete public preset lineage', () => { expect(allModulePresets.map(({ name }) => name)).toEqual([ 'minimal', - 'auth:email', - 'auth:email+magic', - 'auth:sso', - 'auth:passkey', 'auth:hardened', - 'b2b', 'b2b:storage', 'full' ]); }); + test('every preset names a module in the registry', () => { + const known = new Set(allModuleTypes.map(({ name }) => name)); + for (const preset of allModulePresets) { + for (const entry of preset.modules) { + const name = typeof entry === 'string' ? entry : entry[0]; + expect({ preset: preset.name, module: name }).toEqual({ + preset: preset.name, + module: known.has(name) ? name : `` + }); + } + } + }); + + test('every preset extends a preset that still ships', () => { + const names = new Set(allModulePresets.map(({ name }) => name)); + for (const preset of allModulePresets) { + for (const parent of preset.extends ?? []) { + expect(names.has(parent)).toBe(true); + } + } + }); + + test('a preset that installs events asks for a trust ladder', () => { + for (const preset of allModulePresets) { + for (const entry of preset.modules) { + if (typeof entry === 'string' || entry[0] !== 'events_module') continue; + expect({ preset: preset.name, ...entry[1] }).toEqual({ + preset: preset.name, + scope: entry[1].scope, + trust_ladder: 'humanity' + }); + } + } + }); + test('keeps published preset scopes and feature options', () => { const b2bStorage = allModulePresets.find( ({ name }) => name === 'b2b:storage' diff --git a/packages/node-type-registry/src/module-presets/auth-email-magic.ts b/packages/node-type-registry/src/module-presets/auth-email-magic.ts deleted file mode 100644 index d56de3574..000000000 --- a/packages/node-type-registry/src/module-presets/auth-email-magic.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { ModulePreset } from './types'; - -/** - * `auth:email+magic` — `auth:email` plus passwordless email flows. - * - * Adds `session_secrets_module`, which is where one-time nonces for magic - * links and email OTPs are stored. Once installed, the `user_auth_module` - * emits `sign_up_magic_link`, `sign_in_magic_link`, and `sign_in_email_otp` - * procedures (gated on the equivalent `allow_*` toggles in - * `app_settings_auth`). - * - * Choose this over `auth:email` when you want users to be able to log in - * without ever setting a password — but still only over email (no SMS, no - * SSO). - */ -export const PresetAuthEmailMagic: ModulePreset = { - name: 'auth:email+magic', - display_name: 'Email + Magic Link / OTP', - summary: - 'Everything in `auth:email` plus magic-link and email-OTP passwordless flows.', - description: - 'Same password-based auth as `auth:email`, with `session_secrets_module` added so the ' + - 'generator emits the passwordless procedures: `sign_up_magic_link`, `sign_in_magic_link`, ' + - '`sign_in_email_otp`. Password flows still exist — you opt into passwordless-only by ' + - 'flipping the `allow_password_sign_*` toggles off in `app_settings_auth` after install. ' + - 'This is the right step up from `auth:email` when you want to ship magic links without yet ' + - 'taking on SSO or passkeys.', - good_for: [ - 'Consumer apps that want passwordless from day one', - 'Apps targeting users who forget passwords (newsletters, one-off tools)', - 'Hardening path from `auth:email` without jumping all the way to `auth:hardened`', - ], - not_for: [ - 'Apps that need SSO or passkeys — use `auth:sso` or `auth:passkey`', - 'Production at scale — use `auth:hardened` for rate limiting', - ], - modules: [ - 'users_module', - 'membership_types_module', - ['capabilities_module', { scope: 'app' }], - ['limits_module', { scope: 'app' }], - ['levels_module', { scope: 'app' }], - ['memberships_module', { scope: 'app' }], - 'sessions_module', - 'user_state_module', - 'user_credentials_module', - ['internal_secrets_module', { scope: 'app' }], - 'emails_module', - 'rls_module', - 'user_auth_module', - 'session_secrets_module', - ], - extends: ['auth:email'], -}; diff --git a/packages/node-type-registry/src/module-presets/auth-email.ts b/packages/node-type-registry/src/module-presets/auth-email.ts deleted file mode 100644 index d33d4ca8e..000000000 --- a/packages/node-type-registry/src/module-presets/auth-email.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { ModulePreset } from './types'; - -/** - * `auth:email` — email + password sign_up/sign_in. No orgs, no SSO, no SMS, - * no passkeys, no rate limits. - * - * This is the "working consumer login in one step" preset. It installs the - * `user_auth_module` and all the tables its insert trigger hard-requires, - * giving you the standard procedures: `sign_up`, `sign_in`, `sign_out`, - * `set_password`, `reset_password`, `forgot_password`, `verify_email`, - * `delete_account`, `my_sessions`, API-key CRUD. Nothing more. - * - * Includes capabilities, limits, and levels modules (app scope) because - * the app-scoped memberships module has NOT NULL foreign keys to the - * tables they create (grants, caps, levels). - * - * It deliberately excludes rate limits, connected accounts / identity - * providers (OAuth), WebAuthn (passkeys), phone numbers (SMS), invites, - * and org-scoped memberships. Bolt those on by moving to a richer preset - * (`auth:hardened`, `b2b`) when you actually need them. - */ -export const PresetAuthEmail: ModulePreset = { - name: 'auth:email', - display_name: 'Email + Password', - summary: - 'Standard email/password auth flow with app-level capabilities. No orgs, no SSO, no MFA.', - description: - 'Installs `user_auth_module` with exactly the table dependencies its insert trigger ' + - 'hard-requires: users, app-scoped memberships (plus their capabilities/limits/levels ' + - 'dependencies), emails, user state, user secrets, sessions, plus RLS. You get the ' + - 'standard password-based auth procedures (sign_up, sign_in, reset_password, ' + - "verify_email, delete_account, ...) and that's it. Everything else in the module " + - 'catalog — SSO, passkeys, SMS, rate limits, orgs, invites — is deliberately omitted. ' + - 'This is the right shape for single-tenant consumer apps in the first weeks, internal ' + - 'tools that need a real login, or anything where you want the lightest possible working ' + - 'auth and will add complexity only when forced to.', - good_for: [ - 'Single-tenant consumer apps in the first week of development', - 'Internal tools where one simple login is enough', - 'Demos and hobby projects that need real password auth', - 'B2C SaaS before org/team features are needed', - ], - not_for: [ - 'Apps with org/team/workspace structure — use `b2b`', - 'Apps that need SSO or passkeys from day one — use `auth:sso` or `auth:passkey`', - 'Production apps at scale — use `auth:hardened` (adds rate limits, SSO, passkeys, SMS)', - ], - modules: [ - 'users_module', - 'membership_types_module', - ['capabilities_module', { scope: 'app' }], - ['limits_module', { scope: 'app' }], - ['levels_module', { scope: 'app' }], - ['memberships_module', { scope: 'app' }], - 'sessions_module', - 'user_state_module', - 'user_credentials_module', - ['internal_secrets_module', { scope: 'app' }], - 'emails_module', - 'rls_module', - 'user_auth_module', - ], -}; diff --git a/packages/node-type-registry/src/module-presets/auth-hardened.ts b/packages/node-type-registry/src/module-presets/auth-hardened.ts index 82672bcf0..b8614178e 100644 --- a/packages/node-type-registry/src/module-presets/auth-hardened.ts +++ b/packages/node-type-registry/src/module-presets/auth-hardened.ts @@ -1,41 +1,46 @@ import type { ModulePreset } from './types'; /** - * `auth:hardened` — `auth:email` with rate limiting, SSO, passkeys, SMS, - * and magic-link / OTP infrastructure all installed. Production-ready + * `auth:hardened` — email/password auth with rate limiting, SSO, passkeys, + * SMS, and magic-link / OTP infrastructure all installed. Production-ready * consumer auth with the full identifier matrix. * - * Still single-tenant (no orgs / teams / invites / capabilities). For - * multi-tenant B2B, step up to `b2b`. + * Still single-tenant (no orgs / teams / invites). For multi-tenant B2B, + * step up to `b2b:storage`. */ export const PresetAuthHardened: ModulePreset = { name: 'auth:hardened', display_name: 'Hardened (all auth surfaces)', summary: 'Rate limits + SSO + passkeys + SMS + magic links. Production-grade consumer auth.', description: - 'All of `auth:email`, plus every optional auth module that fits inside the single-tenant ' + + 'Email/password sign-in, plus every optional auth module that fits inside the single-tenant ' + 'model: `rate_limits_module` for throttling (protects sign-in, password reset, and ' + 'signup flows), `connected_accounts_module` + `identity_providers_module` for SSO, ' + '`webauthn_credentials_module` + `webauthn_auth_module` for passkeys, ' + '`session_secrets_module` for magic-link / email-OTP nonces, and ' + '`phone_numbers_module` for SMS flows. Every login identifier is available; ' + 'toggle whichever ones you want off via `app_settings_auth.allow_*` columns. ' + - 'Choose this for any production consumer app; step up to `b2b` once you need orgs.', + 'An `events_module` carries the `humanity` trust ladder, so an account can earn ' + + '`level.reachable` from a verified channel and a policy can gate on it. ' + + 'Choose this for any production consumer app; step up to `b2b:storage` once you need orgs.', good_for: [ 'Production consumer apps with a serious user base', 'Apps that need every identifier available (email, SSO, passkey, SMS) with throttling', 'Apps doing a progressive rollout of auth methods — everything is installed, you toggle per method' ], not_for: [ - 'Hobby projects / demos — way too much infrastructure; use `auth:email`', - 'Multi-tenant B2B apps — use `b2b`, which layers orgs + invites + capabilities on top' + 'Hobby projects / demos — way too much infrastructure; use `minimal` and add auth modules', + 'Multi-tenant B2B apps — use `b2b:storage`, which layers orgs + invites + capabilities on top' ], modules: [ 'users_module', 'membership_types_module', ['capabilities_module', { scope: 'app' }], ['limits_module', { scope: 'app' }], - ['levels_module', { scope: 'app' }], + // Levels come from the events module — `levels_module` is not a provisioned + // module, so the entry this replaces installed nothing and an account could + // not earn a level at all. + ['events_module', { scope: 'app', trust_ladder: 'humanity' }], ['memberships_module', { scope: 'app' }], 'sessions_module', 'user_state_module', @@ -53,6 +58,5 @@ export const PresetAuthHardened: ModulePreset = { 'phone_numbers_module', 'devices_module', 'user_settings_security_module' - ], - extends: ['auth:email', 'auth:email+magic', 'auth:sso', 'auth:passkey'] + ] }; diff --git a/packages/node-type-registry/src/module-presets/auth-passkey.ts b/packages/node-type-registry/src/module-presets/auth-passkey.ts deleted file mode 100644 index 203ef4817..000000000 --- a/packages/node-type-registry/src/module-presets/auth-passkey.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { ModulePreset } from './types'; - -/** - * `auth:passkey` — `auth:email` plus WebAuthn / passkeys. - * - * Adds `webauthn_credentials_module` (stores each user's registered public - * keys and credential IDs), `webauthn_auth_module` (the auth-time challenge - * storage + flow), and `session_secrets_module` (where the one-time - * challenge nonces live). The generator then emits WebAuthn registration - * and assertion procedures. - * - * Password flows stay on by default as a recovery path; toggle them off in - * `app_settings_auth` if you want strictly-passkey. - */ -export const PresetAuthPasskey: ModulePreset = { - name: 'auth:passkey', - display_name: 'Passkeys (WebAuthn)', - summary: - 'Email/password auth plus WebAuthn passkey registration and assertion.', - description: - "Installs the three modules WebAuthn needs: `webauthn_credentials_module` for each user's " + - 'registered public keys, `webauthn_auth_module` for the runtime challenge/assertion flow, ' + - 'and `session_secrets_module` for the one-time challenge nonces. With these installed, ' + - 'the generator emits WebAuthn registration/login procs. Keep password flows as a recovery ' + - 'path, or disable them in `app_settings_auth` for passkey-only deployments.', - good_for: [ - 'Apps where you want users to adopt phishing-resistant auth', - 'Consumer apps with a tech-forward audience', - 'Internal tools protecting sensitive data where FIDO2 is a requirement', - ], - not_for: [ - 'Apps that also need SSO or SMS — use `auth:hardened` for everything', - 'Apps where the end-user device mix is heavy on old browsers that lack WebAuthn', - ], - modules: [ - 'users_module', - 'membership_types_module', - ['capabilities_module', { scope: 'app' }], - ['limits_module', { scope: 'app' }], - ['levels_module', { scope: 'app' }], - ['memberships_module', { scope: 'app' }], - 'sessions_module', - 'user_state_module', - 'user_credentials_module', - ['internal_secrets_module', { scope: 'app' }], - 'emails_module', - 'rls_module', - 'user_auth_module', - 'session_secrets_module', - 'webauthn_credentials_module', - 'webauthn_auth_module', - ], - extends: ['auth:email'], -}; diff --git a/packages/node-type-registry/src/module-presets/auth-sso.ts b/packages/node-type-registry/src/module-presets/auth-sso.ts deleted file mode 100644 index 9f7c22a62..000000000 --- a/packages/node-type-registry/src/module-presets/auth-sso.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { ModulePreset } from './types'; - -/** - * `auth:sso` — `auth:email` plus OAuth / OpenID Connect sign-in. - * - * Adds `connected_accounts_module` (the junction table mapping a user to - * `(provider, external_id)`) and `identity_providers_module` (the provider - * config: URLs, client_id, encrypted client_secret, scopes, PKCE/nonce - * knobs). The generator then emits `sign_in_identity` / `sign_up_identity` - * procedures which rely on `internal_secrets_module` to decrypt the client - * secret at auth time. - * - * `oauth_requests_module` covers the leg between those two: while the browser - * is at the provider, the database holds the state it must echo back with the - * PKCE verifier that belongs to it, and any identity that verified but is - * waiting on the account owner to accept a link. `app_settings_auth` - * already declared how long that may take (`oauth_state_max_age`); this is - * what the setting governs. - * - * Password fallback stays on by default (break-glass for admins); flip the - * `allow_password_sign_*` toggles off in `app_settings_auth` for strictly - * SSO-only. - * - * Note: `emails_module` is still required — the `user_auth_module` insert - * trigger hard-requires it today. A pure SSO-only install without emails - * is a separate refactor. - */ -export const PresetAuthSso: ModulePreset = { - name: 'auth:sso', - display_name: 'OAuth / OpenID Connect', - summary: '`auth:email` plus OAuth providers and connected-account linkage.', - description: - 'Adds the two modules that make SSO work: `identity_providers_module` (where provider ' + - 'definitions live — Google, GitHub, Okta, etc., with their URLs, client IDs, and ' + - 'encrypted client secrets) and `connected_accounts_module` (the junction mapping a ' + - 'Constructive user to a `(provider, external_id)` pair). The generator emits ' + - '`sign_in_identity` and `sign_up_identity` procedures which decrypt the client secret ' + - 'through `internal_secrets_module` at auth time. Keep password flows as break-glass, or ' + - 'disable them via `app_settings_auth` toggles for strictly-SSO deployments.', - good_for: [ - 'B2B apps where end users sign in via their employer IdP', - 'Consumer apps that want "Sign in with Google / GitHub"', - 'Apps that need to federate identity with a specific provider ecosystem', - ], - not_for: [ - 'Apps that also need passkeys and rate limits — use `auth:hardened`', - 'Strictly-SSO apps that want NO email storage — needs the emails-optional refactor; not supported by a preset today', - ], - modules: [ - 'users_module', - 'membership_types_module', - ['capabilities_module', { scope: 'app' }], - ['limits_module', { scope: 'app' }], - ['levels_module', { scope: 'app' }], - ['memberships_module', { scope: 'app' }], - 'sessions_module', - 'user_state_module', - 'user_credentials_module', - ['internal_secrets_module', { scope: 'app' }], - 'emails_module', - 'rls_module', - 'user_auth_module', - 'connected_accounts_module', - ['identity_providers_module', { scope: 'app' }], - ['oauth_requests_module', { scope: 'app' }], - ], - extends: ['auth:email'], -}; diff --git a/packages/node-type-registry/src/module-presets/b2b-storage.ts b/packages/node-type-registry/src/module-presets/b2b-storage.ts index b7ce9ed1a..8b39ae3ac 100644 --- a/packages/node-type-registry/src/module-presets/b2b-storage.ts +++ b/packages/node-type-registry/src/module-presets/b2b-storage.ts @@ -1,7 +1,9 @@ import type { ModulePreset } from './types'; /** - * `b2b:storage` — everything in `b2b` plus `storage_module` for file uploads. + * `b2b:storage` — `auth:hardened` plus orgs, invites, capabilities, levels, + * profiles, hierarchy, and `storage_module` for file uploads. The full + * multi-tenant / B2B SaaS shape. * * This is the common shape for B2B SaaS apps that need file upload * infrastructure tied to their org/workspace structure. The storage module @@ -16,8 +18,10 @@ export const PresetB2bStorage: ModulePreset = { display_name: 'B2B SaaS + File Storage', summary: 'Orgs + invites + capabilities + file upload infrastructure (buckets, files, RLS).', description: - 'Everything in `b2b` (auth:hardened + orgs + invites + capabilities + levels + profiles + ' + - 'hierarchy), plus `storage_module` for file uploads. The storage module creates ' + + 'Everything in `auth:hardened`, plus orgs, invites, capabilities, profiles and hierarchy at ' + + 'both app and org membership scopes, an `events_module` at both scopes carrying the ' + + '`humanity` trust ladder (so a member can earn `level.reachable` and a policy can gate on ' + + 'it), and `storage_module` for file uploads. The storage module creates ' + '`app_buckets` and `app_files` tables with full RLS: AuthzPublishable for public reads, ' + 'AuthzAppMembership for member access, AuthzDirectOwner for uploader-only modify/delete. ' + 'Entity-type provisioning with a non-empty `storage` array adds per-scope storage tables ' + @@ -29,8 +33,8 @@ export const PresetB2bStorage: ModulePreset = { 'Apps that need per-entity-type file storage (e.g., project files, team assets)' ], not_for: [ - 'Single-tenant consumer apps — use `auth:email` or `auth:hardened` and add storage separately', - 'Apps without file upload needs — use `b2b` to avoid the storage table overhead' + 'Single-tenant consumer apps — use `auth:hardened` and add storage separately', + 'Apps without file upload needs — drop `storage_module` from the module list' ], modules: [ 'users_module', @@ -39,8 +43,12 @@ export const PresetB2bStorage: ModulePreset = { ['capabilities_module', { scope: 'org' }], ['limits_module', { scope: 'app' }], ['limits_module', { scope: 'org' }], - ['levels_module', { scope: 'app' }], - ['levels_module', { scope: 'org' }], + // Levels come from the events module — `levels_module` is not a provisioned + // module, so the entries this replaces installed nothing and a B2B database + // could not earn a level at all. `humanity` at both scopes: the app ladder + // is seeded at provision, the org ladder rides each organization's insert. + ['events_module', { scope: 'app', trust_ladder: 'humanity' }], + ['events_module', { scope: 'org', trust_ladder: 'humanity' }], ['memberships_module', { scope: 'app' }], ['memberships_module', { scope: 'org' }], 'sessions_module', @@ -71,5 +79,5 @@ export const PresetB2bStorage: ModulePreset = { 'devices_module', 'user_settings_security_module' ], - extends: ['b2b'] + extends: ['auth:hardened'] }; diff --git a/packages/node-type-registry/src/module-presets/b2b.ts b/packages/node-type-registry/src/module-presets/b2b.ts deleted file mode 100644 index cf5d2e7f3..000000000 --- a/packages/node-type-registry/src/module-presets/b2b.ts +++ /dev/null @@ -1,72 +0,0 @@ -import type { ModulePreset } from './types'; - -/** - * `b2b` — `auth:hardened` plus orgs, invites, capabilities, levels, - * profiles, and hierarchy. The full multi-tenant / B2B SaaS shape. - * - * Installs both app-scoped AND org-scoped instances of the membership, - * capability, limit, level, profile, and invite modules. `hierarchy_module` - * at the org scope enables nested org/team structures. - * - * This is a large install — every B2B concept Constructive ships. Don't - * reach for it until you actually need orgs; moving from `auth:hardened` - * to `b2b` later is a provisioning step, not a schema rewrite. - */ -export const PresetB2b: ModulePreset = { - name: 'b2b', - display_name: 'B2B SaaS (orgs + invites + capabilities)', - summary: - '`auth:hardened` + orgs, invites, fine-grained capabilities, levels, profiles, hierarchy.', - description: - 'Everything in `auth:hardened`, plus the full org/team/capability stack at both app and ' + - 'org membership scopes. You get: memberships at org scope, capabilities at app and org ' + - 'scopes for fine-grained RBAC, limits at app and org scopes for per-scope quota ' + - 'enforcement, levels at app and org scopes for role bundles, profiles at app and org ' + - 'scopes for per-scope user display info, hierarchy at org scope for nested org structures, ' + - 'and invites at app and org scopes for invite flows. Choose this when the app has ' + - 'the concept of a "workspace" / "team" / "tenant" that users belong to and act within.', - good_for: [ - 'B2B SaaS with multi-tenant workspaces / teams', - 'Apps where capabilities scope to an organization, not globally', - 'Apps with an invite-based onboarding flow (admins invite members)', - 'Apps that need nested org hierarchies (parent org / sub-org / team)', - ], - not_for: [ - 'Single-tenant consumer apps — use `auth:hardened` or `auth:email`', - 'Apps where all users see the same global dataset — orgs would add overhead with no benefit', - ], - modules: [ - 'users_module', - 'membership_types_module', - ['memberships_module', { scope: 'app' }], - ['memberships_module', { scope: 'org' }], - 'sessions_module', - 'user_state_module', - 'user_credentials_module', - ['internal_secrets_module', { scope: 'app' }], - 'emails_module', - 'rls_module', - 'user_auth_module', - 'session_secrets_module', - 'rate_limits_module', - 'connected_accounts_module', - ['identity_providers_module', { scope: 'app' }], - 'webauthn_credentials_module', - 'webauthn_auth_module', - 'phone_numbers_module', - ['capabilities_module', { scope: 'app' }], - ['capabilities_module', { scope: 'org' }], - ['limits_module', { scope: 'app' }], - ['limits_module', { scope: 'org' }], - ['levels_module', { scope: 'app' }], - ['levels_module', { scope: 'org' }], - ['profiles_module', { scope: 'app' }], - ['profiles_module', { scope: 'org' }], - ['hierarchy_module', { scope: 'org' }], - ['invites_module', { scope: 'app' }], - ['invites_module', { scope: 'org' }], - 'devices_module', - 'user_settings_security_module', - ], - extends: ['auth:hardened'], -}; diff --git a/packages/node-type-registry/src/module-presets/full.ts b/packages/node-type-registry/src/module-presets/full.ts index 71f8bda26..7c4475beb 100644 --- a/packages/node-type-registry/src/module-presets/full.ts +++ b/packages/node-type-registry/src/module-presets/full.ts @@ -18,11 +18,12 @@ export const PresetFull: ModulePreset = { display_name: 'Full (every module)', summary: 'Install every standard Constructive module with explicit module list.', description: - 'Installs every standard module in the catalog: everything in `b2b` plus ' + + 'Installs every standard module in the catalog: everything in `b2b:storage` plus ' + '`storage_module` with all feature flags (versioning, content hash, custom keys, audit log), ' + '`crypto_addresses_module` for wallet-based sign-in, `plans_module` and `billing_module` ' + 'for subscription management, `notifications_module` for in-app notifications, and ' + - '`events_module` at both app and org scopes. Usage logging modules are opt-in only — ' + + '`events_module` at both app and org scopes carrying the `humanity` trust ladder. ' + + 'Usage logging modules are opt-in only — ' + 'add them explicitly if needed.', good_for: [ 'Reference / demo databases that showcase every Constructive feature', @@ -41,13 +42,13 @@ export const PresetFull: ModulePreset = { ['capabilities_module', { scope: 'app' }], ['limits_module', { scope: 'app' }], ['memberships_module', { scope: 'app' }], - ['events_module', { scope: 'app' }], + ['events_module', { scope: 'app', trust_ladder: 'humanity' }], ['profiles_module', { scope: 'app' }], // Org-level (membership_type = 2) ['capabilities_module', { scope: 'org' }], ['limits_module', { scope: 'org' }], ['memberships_module', { scope: 'org' }], - ['events_module', { scope: 'org' }], + ['events_module', { scope: 'org', trust_ladder: 'humanity' }], ['profiles_module', { scope: 'org' }], // Hierarchy ['hierarchy_module', { scope: 'org' }], diff --git a/packages/node-type-registry/src/module-presets/index.ts b/packages/node-type-registry/src/module-presets/index.ts index 2fbfb2365..9841bd5e4 100644 --- a/packages/node-type-registry/src/module-presets/index.ts +++ b/packages/node-type-registry/src/module-presets/index.ts @@ -15,28 +15,13 @@ export type { } from './types'; import { getModuleType } from '../module-types'; -import { PresetAuthEmail } from './auth-email'; -import { PresetAuthEmailMagic } from './auth-email-magic'; import { PresetAuthHardened } from './auth-hardened'; -import { PresetAuthPasskey } from './auth-passkey'; -import { PresetAuthSso } from './auth-sso'; -import { PresetB2b } from './b2b'; import { PresetB2bStorage } from './b2b-storage'; import { PresetFull } from './full'; import { PresetMinimal } from './minimal'; import type { ModulePreset } from './types'; -export { - PresetAuthEmail, - PresetAuthEmailMagic, - PresetAuthHardened, - PresetAuthPasskey, - PresetAuthSso, - PresetB2b, - PresetB2bStorage, - PresetFull, - PresetMinimal, -}; +export { PresetAuthHardened, PresetB2bStorage, PresetFull, PresetMinimal }; /** * Ordered list of all shipped module presets, from smallest to largest @@ -44,12 +29,7 @@ export { */ export const allModulePresets: ModulePreset[] = [ PresetMinimal, - PresetAuthEmail, - PresetAuthEmailMagic, - PresetAuthSso, - PresetAuthPasskey, PresetAuthHardened, - PresetB2b, PresetB2bStorage, PresetFull, ];