node-type-registry 0.44.0 → 0.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +4 -0
  2. package/data/data-i18n.d.ts +2 -0
  3. package/data/data-i18n.js +47 -0
  4. package/data/index.d.ts +1 -0
  5. package/data/index.js +3 -1
  6. package/esm/data/data-i18n.d.ts +2 -0
  7. package/esm/data/data-i18n.js +44 -0
  8. package/esm/data/index.d.ts +1 -0
  9. package/esm/data/index.js +1 -0
  10. package/esm/module-presets/auth-email-magic.js +6 -14
  11. package/esm/module-presets/auth-email.d.ts +3 -3
  12. package/esm/module-presets/auth-email.js +10 -29
  13. package/esm/module-presets/auth-hardened.js +6 -21
  14. package/esm/module-presets/auth-passkey.js +6 -15
  15. package/esm/module-presets/auth-sso.d.ts +1 -1
  16. package/esm/module-presets/auth-sso.js +8 -18
  17. package/esm/module-presets/b2b-storage.js +16 -22
  18. package/esm/module-presets/b2b.js +20 -38
  19. package/esm/module-presets/full.d.ts +1 -1
  20. package/esm/module-presets/full.js +25 -28
  21. package/esm/module-presets/minimal.js +1 -12
  22. package/esm/module-presets/types.d.ts +9 -15
  23. package/module-presets/auth-email-magic.js +6 -14
  24. package/module-presets/auth-email.d.ts +3 -3
  25. package/module-presets/auth-email.js +10 -29
  26. package/module-presets/auth-hardened.js +6 -21
  27. package/module-presets/auth-passkey.js +6 -15
  28. package/module-presets/auth-sso.d.ts +1 -1
  29. package/module-presets/auth-sso.js +8 -18
  30. package/module-presets/b2b-storage.js +16 -22
  31. package/module-presets/b2b.js +20 -38
  32. package/module-presets/full.d.ts +1 -1
  33. package/module-presets/full.js +25 -28
  34. package/module-presets/minimal.js +1 -12
  35. package/module-presets/types.d.ts +9 -15
  36. package/package.json +2 -2
@@ -2,7 +2,7 @@
2
2
  * `full` — install every standard module.
3
3
  *
4
4
  * This is the maximalist preset: every module Constructive ships, including
5
- * `storage_module:full` for file uploads with all feature flags and
5
+ * `storage_module` with all feature flags enabled and
6
6
  * `crypto_addresses_module` for wallet-based sign-in.
7
7
  *
8
8
  * Usage logging modules (compute_log, inference_log, transfer_log,
@@ -16,7 +16,7 @@ export const PresetFull = {
16
16
  display_name: 'Full (every module)',
17
17
  summary: 'Install every standard Constructive module with explicit module list.',
18
18
  description: 'Installs every standard module in the catalog: everything in `b2b` plus ' +
19
- '`storage_module:full` for file uploads (versioning, content hash, custom keys, audit log), ' +
19
+ '`storage_module` with all feature flags (versioning, content hash, custom keys, audit log), ' +
20
20
  '`crypto_addresses_module` for wallet-based sign-in, `plans_module` and `billing_module` ' +
21
21
  'for subscription management, `notifications_module` for in-app notifications, and ' +
22
22
  '`events_module` at both app and org scopes. Usage logging modules are opt-in only — ' +
@@ -35,19 +35,19 @@ export const PresetFull = {
35
35
  'users_module',
36
36
  'membership_types_module',
37
37
  // App-level (membership_type = 1)
38
- 'permissions_module:app',
39
- 'limits_module:app',
40
- 'memberships_module:app',
41
- 'events_module:app',
42
- 'profiles_module:app',
38
+ ['permissions_module', { scope: 'app' }],
39
+ ['limits_module', { scope: 'app' }],
40
+ ['memberships_module', { scope: 'app' }],
41
+ ['events_module', { scope: 'app' }],
42
+ ['profiles_module', { scope: 'app' }],
43
43
  // Org-level (membership_type = 2)
44
- 'permissions_module:org',
45
- 'limits_module:org',
46
- 'memberships_module:org',
47
- 'events_module:org',
48
- 'profiles_module:org',
44
+ ['permissions_module', { scope: 'org' }],
45
+ ['limits_module', { scope: 'org' }],
46
+ ['memberships_module', { scope: 'org' }],
47
+ ['events_module', { scope: 'org' }],
48
+ ['profiles_module', { scope: 'org' }],
49
49
  // Hierarchy
50
- 'hierarchy_module:org',
50
+ ['hierarchy_module', { scope: 'org' }],
51
51
  // Billing & Plans
52
52
  'plans_module',
53
53
  'billing_module',
@@ -59,35 +59,32 @@ export const PresetFull = {
59
59
  'session_secrets_module',
60
60
  'rate_limits_module',
61
61
  'devices_module',
62
- 'config_secrets_user_module',
62
+ 'user_credentials_module',
63
+ 'config_secrets_module',
63
64
  'rls_module',
64
65
  // Contact modules
65
66
  'emails_module',
66
67
  'phone_numbers_module',
67
68
  'crypto_addresses_module',
68
69
  'webauthn_credentials_module',
70
+ // User settings + notifications (user_settings_module must precede notifications_module)
71
+ 'user_settings_module',
69
72
  'notifications_module',
70
73
  // Connected accounts
71
74
  'connected_accounts_module',
72
75
  'identity_providers_module',
73
76
  // Invites & Auth
74
- 'invites_module:app',
75
- 'invites_module:org',
77
+ ['invites_module', { scope: 'app' }],
78
+ ['invites_module', { scope: 'org' }],
76
79
  'user_auth_module',
77
80
  'webauthn_auth_module',
81
+ // Internationalization
82
+ 'i18n_module',
78
83
  // Storage (full features)
79
- 'storage_module:full'
84
+ ['storage_module', { has_versioning: true, has_content_hash: true, has_custom_keys: true, has_audit_log: true }],
85
+ // Infrastructure (functions, namespaces)
86
+ 'namespace_module',
87
+ 'function_module',
80
88
  ],
81
- includes_notes: {
82
- 'storage_module:full': 'All storage feature flags enabled: versioning, content hash, custom keys, audit log.',
83
- billing_module: 'Metered billing with credits waterfall and period reset.',
84
- plans_module: 'Subscription plan management with plan-governed caps.',
85
- notifications_module: 'In-app notification system with read/unread tracking.'
86
- },
87
- omits_notes: {
88
- compute_log_module: 'Usage logging is opt-in. Add explicitly if needed.',
89
- inference_log_module: 'Usage logging is opt-in. Add explicitly if needed.',
90
- agent_module: 'Agent infrastructure is opt-in.'
91
- },
92
89
  extends: ['b2b']
93
90
  };
@@ -33,16 +33,5 @@ export const PresetMinimal = {
33
33
  'sessions_module',
34
34
  'rls_module',
35
35
  'user_state_module'
36
- ],
37
- includes_notes: {
38
- users_module: 'The canonical users table. Required by every preset.',
39
- sessions_module: 'Session/token storage; needed so whatever upstream auth can mint a session row.',
40
- rls_module: 'RLS policy infrastructure. Without it, row-level security is not enforced.',
41
- user_state_module: 'API-key storage. Optional for this preset but almost always wanted alongside upstream auth.'
42
- },
43
- omits_notes: {
44
- user_auth_module: 'No server-side sign_up/sign_in procedures in this preset.',
45
- emails_module: 'Not needed without password/magic-link flows; upstream auth handles identity.',
46
- memberships_module: 'No memberships without a user_auth_module wiring them up.'
47
- }
36
+ ]
48
37
  };
@@ -34,24 +34,18 @@ export interface ModulePreset {
34
34
  /** Scenarios where this preset is the wrong choice — point at alternatives. */
35
35
  not_for: string[];
36
36
  /**
37
- * Flat list of module names to install. Module names must match the
38
- * canonical list accepted by
37
+ * List of modules to install. Each entry is either a plain module name
38
+ * (string) or a Babel-style tuple [name, options] for modules that need
39
+ * configuration. Module names must match the canonical list accepted by
39
40
  * `metaschema_generators.provision_database_modules` in constructive-db.
40
41
  * Order doesn't matter — provisioning resolves dependencies.
42
+ *
43
+ * Examples:
44
+ * 'users_module' — simple module
45
+ * ['permissions_module', { scope: 'app' }] — scoped module
46
+ * ['agent_module', { has_plans: true }] — feature-flagged module
41
47
  */
42
- modules: string[];
43
- /**
44
- * Optional per-module justifications. Map from module name to a short
45
- * "why this module is in this preset" note. Rendered in docs and CLI
46
- * `--explain` output.
47
- */
48
- includes_notes?: Record<string, string>;
49
- /**
50
- * Optional per-module "why we deliberately leave this out" notes. Only
51
- * list modules that a user might reasonably expect to be here; don't
52
- * enumerate every omitted module.
53
- */
54
- omits_notes?: Record<string, string>;
48
+ modules: (string | [string, Record<string, unknown>])[];
55
49
  /**
56
50
  * Optional: name(s) of presets this one builds on. Purely documentary —
57
51
  * not enforced at runtime, `modules` must still be the full flat list.
@@ -36,26 +36,18 @@ exports.PresetAuthEmailMagic = {
36
36
  modules: [
37
37
  'users_module',
38
38
  'membership_types_module',
39
- 'permissions_module:app',
40
- 'limits_module:app',
41
- 'levels_module:app',
42
- 'memberships_module:app',
39
+ ['permissions_module', { scope: 'app' }],
40
+ ['limits_module', { scope: 'app' }],
41
+ ['levels_module', { scope: 'app' }],
42
+ ['memberships_module', { scope: 'app' }],
43
43
  'sessions_module',
44
44
  'user_state_module',
45
- 'config_secrets_user_module',
45
+ 'user_credentials_module',
46
+ 'config_secrets_module',
46
47
  'emails_module',
47
48
  'rls_module',
48
49
  'user_auth_module',
49
50
  'session_secrets_module'
50
51
  ],
51
- includes_notes: {
52
- session_secrets_module: 'Stores nonces for magic-link and email-OTP flows. Without it those procedures are not emitted.'
53
- },
54
- omits_notes: {
55
- rate_limits_module: 'Same reasoning as `auth:email` — add later via `auth:hardened`.',
56
- connected_accounts_module: 'No OAuth / SSO in this preset.',
57
- webauthn_credentials_module: 'No passkeys — add `auth:passkey`.',
58
- phone_numbers_module: 'No SMS — add `auth:hardened`.'
59
- },
60
52
  extends: ['auth:email']
61
53
  };
@@ -9,9 +9,9 @@ import type { ModulePreset } from './types';
9
9
  * `set_password`, `reset_password`, `forgot_password`, `verify_email`,
10
10
  * `delete_account`, `my_sessions`, API-key CRUD. Nothing more.
11
11
  *
12
- * Includes `permissions_module:app`, `limits_module:app`, and
13
- * `levels_module:app` because `memberships_module:app` has NOT NULL
14
- * foreign keys to the tables they create (grants, caps, levels).
12
+ * Includes permissions, limits, and levels modules (app scope) because
13
+ * the app-scoped memberships module has NOT NULL foreign keys to the
14
+ * tables they create (grants, caps, levels).
15
15
  *
16
16
  * It deliberately excludes rate limits, connected accounts / identity
17
17
  * providers (OAuth), WebAuthn (passkeys), phone numbers (SMS), invites,
@@ -11,9 +11,9 @@ exports.PresetAuthEmail = void 0;
11
11
  * `set_password`, `reset_password`, `forgot_password`, `verify_email`,
12
12
  * `delete_account`, `my_sessions`, API-key CRUD. Nothing more.
13
13
  *
14
- * Includes `permissions_module:app`, `limits_module:app`, and
15
- * `levels_module:app` because `memberships_module:app` has NOT NULL
16
- * foreign keys to the tables they create (grants, caps, levels).
14
+ * Includes permissions, limits, and levels modules (app scope) because
15
+ * the app-scoped memberships module has NOT NULL foreign keys to the
16
+ * tables they create (grants, caps, levels).
17
17
  *
18
18
  * It deliberately excludes rate limits, connected accounts / identity
19
19
  * providers (OAuth), WebAuthn (passkeys), phone numbers (SMS), invites,
@@ -47,35 +47,16 @@ exports.PresetAuthEmail = {
47
47
  modules: [
48
48
  'users_module',
49
49
  'membership_types_module',
50
- 'permissions_module:app',
51
- 'limits_module:app',
52
- 'levels_module:app',
53
- 'memberships_module:app',
50
+ ['permissions_module', { scope: 'app' }],
51
+ ['limits_module', { scope: 'app' }],
52
+ ['levels_module', { scope: 'app' }],
53
+ ['memberships_module', { scope: 'app' }],
54
54
  'sessions_module',
55
55
  'user_state_module',
56
- 'config_secrets_user_module',
56
+ 'user_credentials_module',
57
+ 'config_secrets_module',
57
58
  'emails_module',
58
59
  'rls_module',
59
60
  'user_auth_module'
60
- ],
61
- includes_notes: {
62
- 'memberships_module:app': 'Required by `user_auth_module`: every user gets an app-level membership row at sign-up.',
63
- membership_types_module: "Required by `memberships_module:app`; defines the 'app' scope.",
64
- 'permissions_module:app': 'Required by `memberships_module:app`: NOT NULL FK to grants table.',
65
- 'limits_module:app': 'Required by `memberships_module:app`: NOT NULL FK to caps table.',
66
- 'levels_module:app': 'Required by `memberships_module:app`: NOT NULL FK to levels table.',
67
- emails_module: 'Required by the `user_auth_module` insert trigger (`RAISE EXCEPTION REQUIRES emails_module`).',
68
- config_secrets_user_module: 'Required for password hashing; referenced by `set_password`, `verify_password`, and reset flows.',
69
- user_state_module: 'API-key storage (`create_api_key`, `revoke_api_key`, `my_api_keys`).'
70
- },
71
- omits_notes: {
72
- rate_limits_module: 'Omitted intentionally; throttle_* helpers are null-safe and the auth procs compile without it. Add later via `auth:hardened`.',
73
- connected_accounts_module: 'No OAuth / SSO in this preset — add `auth:sso`.',
74
- identity_providers_module: 'No OAuth provider configs without connected_accounts.',
75
- webauthn_credentials_module: 'No passkeys — add `auth:passkey`.',
76
- phone_numbers_module: 'No SMS login — add `auth:hardened` or the SMS-only refactor path.',
77
- 'memberships_module:org': 'No org/team structure — move to `b2b` when you need one.',
78
- invites_module: 'Self-serve signup only.',
79
- session_secrets_module: 'No magic-link / email-OTP nonces; add `auth:email+magic`.'
80
- }
61
+ ]
81
62
  };
@@ -33,13 +33,14 @@ exports.PresetAuthHardened = {
33
33
  modules: [
34
34
  'users_module',
35
35
  'membership_types_module',
36
- 'permissions_module:app',
37
- 'limits_module:app',
38
- 'levels_module:app',
39
- 'memberships_module:app',
36
+ ['permissions_module', { scope: 'app' }],
37
+ ['limits_module', { scope: 'app' }],
38
+ ['levels_module', { scope: 'app' }],
39
+ ['memberships_module', { scope: 'app' }],
40
40
  'sessions_module',
41
41
  'user_state_module',
42
- 'config_secrets_user_module',
42
+ 'user_credentials_module',
43
+ 'config_secrets_module',
43
44
  'emails_module',
44
45
  'rls_module',
45
46
  'user_auth_module',
@@ -52,21 +53,5 @@ exports.PresetAuthHardened = {
52
53
  'phone_numbers_module',
53
54
  'devices_module'
54
55
  ],
55
- includes_notes: {
56
- rate_limits_module: 'Throttling for sign-in, password reset, sign-up, and IP-based gates.',
57
- connected_accounts_module: 'OAuth / SSO linkage.',
58
- identity_providers_module: 'OAuth provider configs (required for `connected_accounts_module`).',
59
- webauthn_credentials_module: 'Per-user passkey storage.',
60
- webauthn_auth_module: 'Passkey challenge + assertion runtime.',
61
- session_secrets_module: 'Nonces for magic links, email OTP, and WebAuthn challenges.',
62
- phone_numbers_module: 'SMS sign-in / MFA support.',
63
- devices_module: 'Device tracking and trusted-device MFA bypass.'
64
- },
65
- omits_notes: {
66
- 'memberships_module:org': 'No orgs / teams — use `b2b` when you need multi-tenancy.',
67
- invites_module: 'No invite flow — add via `b2b`.',
68
- storage_module: 'Add separately if you need file uploads.',
69
- crypto_addresses_module: 'Not a web3 preset; omit unless doing wallet sign-in.'
70
- },
71
56
  extends: ['auth:email', 'auth:email+magic', 'auth:sso', 'auth:passkey']
72
57
  };
@@ -34,13 +34,14 @@ exports.PresetAuthPasskey = {
34
34
  modules: [
35
35
  'users_module',
36
36
  'membership_types_module',
37
- 'permissions_module:app',
38
- 'limits_module:app',
39
- 'levels_module:app',
40
- 'memberships_module:app',
37
+ ['permissions_module', { scope: 'app' }],
38
+ ['limits_module', { scope: 'app' }],
39
+ ['levels_module', { scope: 'app' }],
40
+ ['memberships_module', { scope: 'app' }],
41
41
  'sessions_module',
42
42
  'user_state_module',
43
- 'config_secrets_user_module',
43
+ 'user_credentials_module',
44
+ 'config_secrets_module',
44
45
  'emails_module',
45
46
  'rls_module',
46
47
  'user_auth_module',
@@ -48,15 +49,5 @@ exports.PresetAuthPasskey = {
48
49
  'webauthn_credentials_module',
49
50
  'webauthn_auth_module'
50
51
  ],
51
- includes_notes: {
52
- webauthn_credentials_module: 'Per-user WebAuthn credential storage. Without it, passkey registration does not compile.',
53
- webauthn_auth_module: 'Runtime challenge + assertion flow.',
54
- session_secrets_module: 'Challenge nonces for registration and assertion.'
55
- },
56
- omits_notes: {
57
- rate_limits_module: 'Add via `auth:hardened` for production.',
58
- connected_accounts_module: 'No OAuth / SSO — add via `auth:hardened`.',
59
- phone_numbers_module: 'No SMS.'
60
- },
61
52
  extends: ['auth:email']
62
53
  };
@@ -6,7 +6,7 @@ import type { ModulePreset } from './types';
6
6
  * `(provider, external_id)`) and `identity_providers_module` (the provider
7
7
  * config: URLs, client_id, encrypted client_secret, scopes, PKCE/nonce
8
8
  * knobs). The generator then emits `sign_in_identity` / `sign_up_identity`
9
- * procedures which rely on `config_secrets_user_module` to decrypt the client
9
+ * procedures which rely on `config_secrets_module` to decrypt the client
10
10
  * secret at auth time.
11
11
  *
12
12
  * Password fallback stays on by default (break-glass for admins); flip the
@@ -8,7 +8,7 @@ exports.PresetAuthSso = void 0;
8
8
  * `(provider, external_id)`) and `identity_providers_module` (the provider
9
9
  * config: URLs, client_id, encrypted client_secret, scopes, PKCE/nonce
10
10
  * knobs). The generator then emits `sign_in_identity` / `sign_up_identity`
11
- * procedures which rely on `config_secrets_user_module` to decrypt the client
11
+ * procedures which rely on `config_secrets_module` to decrypt the client
12
12
  * secret at auth time.
13
13
  *
14
14
  * Password fallback stays on by default (break-glass for admins); flip the
@@ -29,7 +29,7 @@ exports.PresetAuthSso = {
29
29
  'encrypted client secrets) and `connected_accounts_module` (the junction mapping a ' +
30
30
  'Constructive user to a `(provider, external_id)` pair). The generator emits ' +
31
31
  '`sign_in_identity` and `sign_up_identity` procedures which decrypt the client secret ' +
32
- 'through `config_secrets_user_module` at auth time. Keep password flows as break-glass, or ' +
32
+ 'through `config_secrets_module` at auth time. Keep password flows as break-glass, or ' +
33
33
  'disable them via `app_settings_auth` toggles for strictly-SSO deployments.',
34
34
  good_for: [
35
35
  'B2B apps where end users sign in via their employer IdP',
@@ -43,29 +43,19 @@ exports.PresetAuthSso = {
43
43
  modules: [
44
44
  'users_module',
45
45
  'membership_types_module',
46
- 'permissions_module:app',
47
- 'limits_module:app',
48
- 'levels_module:app',
49
- 'memberships_module:app',
46
+ ['permissions_module', { scope: 'app' }],
47
+ ['limits_module', { scope: 'app' }],
48
+ ['levels_module', { scope: 'app' }],
49
+ ['memberships_module', { scope: 'app' }],
50
50
  'sessions_module',
51
51
  'user_state_module',
52
- 'config_secrets_user_module',
52
+ 'user_credentials_module',
53
+ 'config_secrets_module',
53
54
  'emails_module',
54
55
  'rls_module',
55
56
  'user_auth_module',
56
57
  'connected_accounts_module',
57
58
  'identity_providers_module'
58
59
  ],
59
- includes_notes: {
60
- connected_accounts_module: 'Junction table for (user, provider, external_id). Without it, `sign_in_identity` does not compile.',
61
- identity_providers_module: 'Provider config table (URLs, client_id, encrypted client_secret, scopes, PKCE knobs).',
62
- config_secrets_user_module: 'Required by `auth:email` already; also used by SSO to decrypt the provider client_secret at auth time.'
63
- },
64
- omits_notes: {
65
- webauthn_credentials_module: 'No passkeys — add `auth:passkey` or move to `auth:hardened`.',
66
- rate_limits_module: 'Omitted; add via `auth:hardened` for production.',
67
- session_secrets_module: "Not required for authorization-code OAuth; add if you also want magic-link flows. PKCE doesn't require it for stateless OAuth flows today.",
68
- phone_numbers_module: 'No SMS in this preset.'
69
- },
70
60
  extends: ['auth:email']
71
61
  };
@@ -21,7 +21,7 @@ exports.PresetB2bStorage = {
21
21
  '`app_buckets` and `app_files` tables with full RLS: AuthzPublishable for public reads, ' +
22
22
  'AuthzAppMembership for member access, AuthzDirectOwner for uploader-only modify/delete. ' +
23
23
  'Entity-type provisioning with a non-empty `storage` array adds per-scope storage tables ' +
24
- 'automatically (multiple modules per entity via storage_key). Choose this when your B2B ' +
24
+ 'automatically (multiple modules per entity via key). Choose this when your B2B ' +
25
25
  'app needs file uploads, avatars, attachments, or any object storage tied to workspaces.',
26
26
  good_for: [
27
27
  'B2B SaaS with file uploads (documents, avatars, attachments)',
@@ -35,17 +35,18 @@ exports.PresetB2bStorage = {
35
35
  modules: [
36
36
  'users_module',
37
37
  'membership_types_module',
38
- 'permissions_module:app',
39
- 'permissions_module:org',
40
- 'limits_module:app',
41
- 'limits_module:org',
42
- 'levels_module:app',
43
- 'levels_module:org',
44
- 'memberships_module:app',
45
- 'memberships_module:org',
38
+ ['permissions_module', { scope: 'app' }],
39
+ ['permissions_module', { scope: 'org' }],
40
+ ['limits_module', { scope: 'app' }],
41
+ ['limits_module', { scope: 'org' }],
42
+ ['levels_module', { scope: 'app' }],
43
+ ['levels_module', { scope: 'org' }],
44
+ ['memberships_module', { scope: 'app' }],
45
+ ['memberships_module', { scope: 'org' }],
46
46
  'sessions_module',
47
47
  'user_state_module',
48
- 'config_secrets_user_module',
48
+ 'user_credentials_module',
49
+ 'config_secrets_module',
49
50
  'emails_module',
50
51
  'rls_module',
51
52
  'user_auth_module',
@@ -56,20 +57,13 @@ exports.PresetB2bStorage = {
56
57
  'webauthn_credentials_module',
57
58
  'webauthn_auth_module',
58
59
  'phone_numbers_module',
59
- 'profiles_module:app',
60
- 'profiles_module:org',
61
- 'hierarchy_module:org',
62
- 'invites_module:app',
63
- 'invites_module:org',
60
+ ['profiles_module', { scope: 'app' }],
61
+ ['profiles_module', { scope: 'org' }],
62
+ ['hierarchy_module', { scope: 'org' }],
63
+ ['invites_module', { scope: 'app' }],
64
+ ['invites_module', { scope: 'org' }],
64
65
  'storage_module',
65
66
  'devices_module'
66
67
  ],
67
- includes_notes: {
68
- storage_module: 'File upload infrastructure: app_buckets + app_files tables with RLS. Entity-type storage scopes layered on top via the `storage` array (array-only format, supports multiple modules per entity via storage_key).',
69
- devices_module: 'Device tracking and trusted-device MFA bypass.'
70
- },
71
- omits_notes: {
72
- crypto_addresses_module: 'Not a web3 preset.'
73
- },
74
68
  extends: ['b2b']
75
69
  };
@@ -18,11 +18,11 @@ exports.PresetB2b = {
18
18
  display_name: 'B2B SaaS (orgs + invites + permissions)',
19
19
  summary: '`auth:hardened` + orgs, invites, fine-grained permissions, levels, profiles, hierarchy.',
20
20
  description: 'Everything in `auth:hardened`, plus the full org/team/permission stack at both app and ' +
21
- 'org membership scopes. You get: `memberships_module:org` for org-scoped memberships, ' +
22
- '`permissions_module:app/:org` for fine-grained RBAC, `limits_module:app/:org` for per-scope ' +
23
- 'quota enforcement, `levels_module:app/:org` for role bundles, `profiles_module:app/:org` ' +
24
- 'for per-scope user display info, `hierarchy_module:org` for nested org structures, and ' +
25
- '`invites_module:app/:org` for invite flows at either scope. Choose this when the app has ' +
21
+ 'org membership scopes. You get: memberships at org scope, permissions at app and org ' +
22
+ 'scopes for fine-grained RBAC, limits at app and org scopes for per-scope quota ' +
23
+ 'enforcement, levels at app and org scopes for role bundles, profiles at app and org ' +
24
+ 'scopes for per-scope user display info, hierarchy at org scope for nested org structures, ' +
25
+ 'and invites at app and org scopes for invite flows. Choose this when the app has ' +
26
26
  'the concept of a "workspace" / "team" / "tenant" that users belong to and act within.',
27
27
  good_for: [
28
28
  'B2B SaaS with multi-tenant workspaces / teams',
@@ -37,11 +37,12 @@ exports.PresetB2b = {
37
37
  modules: [
38
38
  'users_module',
39
39
  'membership_types_module',
40
- 'memberships_module:app',
41
- 'memberships_module:org',
40
+ ['memberships_module', { scope: 'app' }],
41
+ ['memberships_module', { scope: 'org' }],
42
42
  'sessions_module',
43
43
  'user_state_module',
44
- 'config_secrets_user_module',
44
+ 'user_credentials_module',
45
+ 'config_secrets_module',
45
46
  'emails_module',
46
47
  'rls_module',
47
48
  'user_auth_module',
@@ -52,37 +53,18 @@ exports.PresetB2b = {
52
53
  'webauthn_credentials_module',
53
54
  'webauthn_auth_module',
54
55
  'phone_numbers_module',
55
- 'permissions_module:app',
56
- 'permissions_module:org',
57
- 'limits_module:app',
58
- 'limits_module:org',
59
- 'levels_module:app',
60
- 'levels_module:org',
61
- 'profiles_module:app',
62
- 'profiles_module:org',
63
- 'hierarchy_module:org',
64
- 'invites_module:app',
65
- 'invites_module:org',
56
+ ['permissions_module', { scope: 'app' }],
57
+ ['permissions_module', { scope: 'org' }],
58
+ ['limits_module', { scope: 'app' }],
59
+ ['limits_module', { scope: 'org' }],
60
+ ['levels_module', { scope: 'app' }],
61
+ ['levels_module', { scope: 'org' }],
62
+ ['profiles_module', { scope: 'app' }],
63
+ ['profiles_module', { scope: 'org' }],
64
+ ['hierarchy_module', { scope: 'org' }],
65
+ ['invites_module', { scope: 'app' }],
66
+ ['invites_module', { scope: 'org' }],
66
67
  'devices_module'
67
68
  ],
68
- includes_notes: {
69
- 'memberships_module:org': 'Org-scoped membership rows — every user in an org gets one.',
70
- 'permissions_module:app': 'App-wide permission grants (e.g. platform admins).',
71
- 'permissions_module:org': 'Org-scoped permission grants (per-workspace admins, members, viewers, ...).',
72
- 'limits_module:app': 'App-level quotas (e.g. max users per plan).',
73
- 'limits_module:org': 'Org-level quotas (e.g. per-workspace API call caps).',
74
- 'levels_module:app': 'Role/level bundles at the app scope.',
75
- 'levels_module:org': 'Role/level bundles at the org scope (admin / member / viewer, etc.).',
76
- 'profiles_module:app': 'App-scoped user profile (one per user).',
77
- 'profiles_module:org': 'Org-scoped user profile (per org a user belongs to).',
78
- 'hierarchy_module:org': 'Nested org structures (parent / child orgs).',
79
- 'invites_module:app': 'App-level invites (rare — usually platform admin adds another admin).',
80
- 'invites_module:org': 'Org-level invites (the common case — invite a teammate into a workspace).',
81
- devices_module: 'Device tracking and trusted-device MFA bypass.'
82
- },
83
- omits_notes: {
84
- storage_module: 'Add separately if you need file uploads tied to orgs.',
85
- crypto_addresses_module: 'Not a web3 preset.'
86
- },
87
69
  extends: ['auth:hardened']
88
70
  };
@@ -3,7 +3,7 @@ import type { ModulePreset } from './types';
3
3
  * `full` — install every standard module.
4
4
  *
5
5
  * This is the maximalist preset: every module Constructive ships, including
6
- * `storage_module:full` for file uploads with all feature flags and
6
+ * `storage_module` with all feature flags enabled and
7
7
  * `crypto_addresses_module` for wallet-based sign-in.
8
8
  *
9
9
  * Usage logging modules (compute_log, inference_log, transfer_log,