Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export const PresetAuthEmailMagic: ModulePreset = {
modules: [
'users_module',
'membership_types_module',
'permissions_module:app',
'limits_module:app',
'levels_module:app',
'memberships_module:app',
'sessions_module',
'secrets_module',
Expand Down
33 changes: 21 additions & 12 deletions packages/node-type-registry/src/module-presets/auth-email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,29 @@ import type { ModulePreset } from './types';
* `set_password`, `reset_password`, `forgot_password`, `verify_email`,
* `delete_account`, `my_sessions`, API-key CRUD. Nothing more.
*
* Includes `permissions_module:app`, `limits_module:app`, and
* `levels_module:app` because `memberships_module:app` 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,
* permissions, and org-scoped memberships. Bolt those on by moving to a
* richer preset (`auth:hardened`, `b2b`) when you actually need them.
* 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. No orgs, no SSO, no MFA, no rate limits.',
summary: 'Standard email/password auth flow with app-level permissions. 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, emails, secrets, encrypted 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, permissions — 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.',
'hard-requires: users, app-scoped memberships (plus their permissions/limits/levels ' +
'dependencies), emails, secrets, encrypted 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',
Expand All @@ -43,6 +47,9 @@ export const PresetAuthEmail: ModulePreset = {
modules: [
'users_module',
'membership_types_module',
'permissions_module:app',
'limits_module:app',
'levels_module:app',
'memberships_module:app',
'sessions_module',
'secrets_module',
Expand All @@ -54,6 +61,9 @@ export const PresetAuthEmail: ModulePreset = {
includes_notes: {
'memberships_module:app': 'Required by `user_auth_module`: every user gets an app-level membership row at sign-up.',
membership_types_module: "Required by `memberships_module:app`; defines the 'app' scope.",
'permissions_module:app': 'Required by `memberships_module:app`: NOT NULL FK to grants table.',
'limits_module:app': 'Required by `memberships_module:app`: NOT NULL FK to caps table.',
'levels_module:app': 'Required by `memberships_module:app`: NOT NULL FK to levels table.',
emails_module: 'Required by the `user_auth_module` insert trigger (`RAISE EXCEPTION REQUIRES emails_module`).',
encrypted_secrets_module: 'Required for password hashing; referenced by `set_password`, `verify_password`, and reset flows.',
secrets_module: 'API-key storage (`create_api_key`, `revoke_api_key`, `my_api_keys`).'
Expand All @@ -65,7 +75,6 @@ export const PresetAuthEmail: ModulePreset = {
webauthn_credentials_module: 'No passkeys — add `auth:passkey`.',
phone_numbers_module: 'No SMS login — add `auth:hardened` or the SMS-only refactor path.',
'memberships_module:org': 'No org/team structure — move to `b2b` when you need one.',
'permissions_module:app': 'No fine-grained RBAC; the `is_admin` flag on users is the only gate.',
invites_module: 'Self-serve signup only.',
session_secrets_module: 'No magic-link / email-OTP nonces; add `auth:email+magic`.'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ export const PresetAuthHardened: ModulePreset = {
modules: [
'users_module',
'membership_types_module',
'permissions_module:app',
'limits_module:app',
'levels_module:app',
'memberships_module:app',
'sessions_module',
'secrets_module',
Expand All @@ -59,7 +62,6 @@ export const PresetAuthHardened: ModulePreset = {
},
omits_notes: {
'memberships_module:org': 'No orgs / teams — use `b2b` when you need multi-tenancy.',
'permissions_module:app': 'No RBAC beyond the `is_admin` flag — add via `b2b`.',
invites_module: 'No invite flow — add via `b2b`.',
storage_module: 'Add separately if you need file uploads.',
crypto_addresses_module: 'Not a web3 preset; omit unless doing wallet sign-in.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ export const PresetAuthPasskey: ModulePreset = {
modules: [
'users_module',
'membership_types_module',
'permissions_module:app',
'limits_module:app',
'levels_module:app',
'memberships_module:app',
'sessions_module',
'secrets_module',
Expand Down
3 changes: 3 additions & 0 deletions packages/node-type-registry/src/module-presets/auth-sso.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ export const PresetAuthSso: ModulePreset = {
modules: [
'users_module',
'membership_types_module',
'permissions_module:app',
'limits_module:app',
'levels_module:app',
'memberships_module:app',
'sessions_module',
'secrets_module',
Expand Down
73 changes: 73 additions & 0 deletions packages/node-type-registry/src/module-presets/b2b-storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import type { ModulePreset } from './types';

/**
* `b2b:storage` — everything in `b2b` plus `storage_module` for file uploads.
*
* This is the common shape for B2B SaaS apps that need file upload
* infrastructure tied to their org/workspace structure. The storage module
* creates `app_buckets` and `app_files` tables with RLS policies, and
* entity-type-level storage scopes can be provisioned on top.
*
* If you don't need orgs, use a lighter preset and add `storage_module`
* separately via provisioning options.
*/
export const PresetB2bStorage: ModulePreset = {
name: 'b2b:storage',
display_name: 'B2B SaaS + File Storage',
summary: '`b2b` + file upload infrastructure (buckets, files, RLS).',
description:
'Everything in `b2b` (auth:hardened + orgs + invites + permissions + levels + profiles + ' +
'hierarchy), plus `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 `has_storage=true` adds per-scope storage tables ' +
'automatically. Choose this when your B2B app needs file uploads, avatars, attachments, ' +
'or any object storage tied to workspaces.',
good_for: [
'B2B SaaS with file uploads (documents, avatars, attachments)',
'Apps where storage is scoped to orgs/workspaces',
'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'
],
modules: [
'users_module',
'membership_types_module',
'permissions_module:app',
'permissions_module:org',
'limits_module:app',
'limits_module:org',
'levels_module:app',
'levels_module:org',
'memberships_module:app',
'memberships_module:org',
'sessions_module',
'secrets_module',
'encrypted_secrets_module',
'emails_module',
'rls_module',
'user_auth_module',
'session_secrets_module',
'rate_limits_module',
'connected_accounts_module',
'identity_providers_module',
'webauthn_credentials_module',
'webauthn_auth_module',
'phone_numbers_module',
'profiles_module:app',
'profiles_module:org',
'hierarchy_module:org',
'invites_module:app',
'invites_module:org',
'storage_module'
],
includes_notes: {
storage_module: 'File upload infrastructure: app_buckets + app_files tables with RLS. Entity-type storage scopes layered on top via `has_storage=true`.'
},
omits_notes: {
crypto_addresses_module: 'Not a web3 preset.'
},
extends: ['b2b']
};
3 changes: 3 additions & 0 deletions packages/node-type-registry/src/module-presets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ 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';
Expand All @@ -17,6 +18,7 @@ export {
PresetAuthPasskey,
PresetAuthSso,
PresetB2b,
PresetB2bStorage,
PresetFull,
PresetMinimal};

Expand All @@ -32,6 +34,7 @@ export const allModulePresets: ModulePreset[] = [
PresetAuthPasskey,
PresetAuthHardened,
PresetB2b,
PresetB2bStorage,
PresetFull
];

Expand Down
Loading