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
2 changes: 1 addition & 1 deletion agentic/pi/__tests__/provision-modules.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});

Expand Down
40 changes: 35 additions & 5 deletions packages/node-type-registry/__tests__/module-types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 : `<unknown module: ${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'
Expand Down
54 changes: 0 additions & 54 deletions packages/node-type-registry/src/module-presets/auth-email-magic.ts

This file was deleted.

63 changes: 0 additions & 63 deletions packages/node-type-registry/src/module-presets/auth-email.ts

This file was deleted.

26 changes: 15 additions & 11 deletions packages/node-type-registry/src/module-presets/auth-hardened.ts
Original file line number Diff line number Diff line change
@@ -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',
Expand All @@ -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']
]
};
54 changes: 0 additions & 54 deletions packages/node-type-registry/src/module-presets/auth-passkey.ts

This file was deleted.

68 changes: 0 additions & 68 deletions packages/node-type-registry/src/module-presets/auth-sso.ts

This file was deleted.

Loading
Loading