@seifer-webapp-factory/authentication 0.1.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.
- package/README.md +8 -0
- package/backend/templates/config/config-fragment.ts +73 -0
- package/backend/templates/mail/templates.ts +84 -0
- package/backend/templates/nestjs/auth.controller.ts +274 -0
- package/backend/templates/nestjs/auth.module.ts +207 -0
- package/backend/templates/nestjs/tokens.ts +24 -0
- package/backend/templates/persistence/migrations/0001_auth.sql +36 -0
- package/backend/templates/persistence/migrations/index.ts +75 -0
- package/backend/templates/persistence/pg-single-use-store.ts +64 -0
- package/backend/templates/persistence/pg-token-store.ts +75 -0
- package/backend/templates/persistence/pg-user-store.ts +53 -0
- package/backend/templates/security/cookies.ts +89 -0
- package/backend/templates/security/csrf.ts +44 -0
- package/backend/templates/security/headers.ts +30 -0
- package/backend/templates/security/redaction.ts +38 -0
- package/dist/backend/src/errors.d.ts +12 -0
- package/dist/backend/src/errors.d.ts.map +1 -0
- package/dist/backend/src/errors.js +55 -0
- package/dist/backend/src/errors.js.map +1 -0
- package/dist/backend/src/index.d.ts +9 -0
- package/dist/backend/src/index.d.ts.map +1 -0
- package/dist/backend/src/index.js +8 -0
- package/dist/backend/src/index.js.map +1 -0
- package/dist/backend/src/ports.d.ts +60 -0
- package/dist/backend/src/ports.d.ts.map +1 -0
- package/dist/backend/src/ports.js +2 -0
- package/dist/backend/src/ports.js.map +1 -0
- package/dist/backend/src/services.d.ts +49 -0
- package/dist/backend/src/services.d.ts.map +1 -0
- package/dist/backend/src/services.js +178 -0
- package/dist/backend/src/services.js.map +1 -0
- package/dist/contract/endpoints.d.ts +259 -0
- package/dist/contract/endpoints.d.ts.map +1 -0
- package/dist/contract/endpoints.js +42 -0
- package/dist/contract/endpoints.js.map +1 -0
- package/dist/contract/errors.d.ts +23 -0
- package/dist/contract/errors.d.ts.map +1 -0
- package/dist/contract/errors.js +31 -0
- package/dist/contract/errors.js.map +1 -0
- package/dist/contract/events.d.ts +40 -0
- package/dist/contract/events.d.ts.map +1 -0
- package/dist/contract/events.js +14 -0
- package/dist/contract/events.js.map +1 -0
- package/dist/contract/index.d.ts +9 -0
- package/dist/contract/index.d.ts.map +1 -0
- package/dist/contract/index.js +9 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/contract/schemas.d.ts +150 -0
- package/dist/contract/schemas.d.ts.map +1 -0
- package/dist/contract/schemas.js +43 -0
- package/dist/contract/schemas.js.map +1 -0
- package/dist/frontend/src/client.d.ts +38 -0
- package/dist/frontend/src/client.d.ts.map +1 -0
- package/dist/frontend/src/client.js +88 -0
- package/dist/frontend/src/client.js.map +1 -0
- package/dist/frontend/src/composables.d.ts +46 -0
- package/dist/frontend/src/composables.d.ts.map +1 -0
- package/dist/frontend/src/composables.js +111 -0
- package/dist/frontend/src/composables.js.map +1 -0
- package/dist/frontend/src/guards.d.ts +10 -0
- package/dist/frontend/src/guards.d.ts.map +1 -0
- package/dist/frontend/src/guards.js +9 -0
- package/dist/frontend/src/guards.js.map +1 -0
- package/dist/frontend/src/index.d.ts +12 -0
- package/dist/frontend/src/index.d.ts.map +1 -0
- package/dist/frontend/src/index.js +9 -0
- package/dist/frontend/src/index.js.map +1 -0
- package/dist/manifest.d.ts +80 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +126 -0
- package/dist/manifest.js.map +1 -0
- package/dist/scaffolder/core/config.d.ts +213 -0
- package/dist/scaffolder/core/config.d.ts.map +1 -0
- package/dist/scaffolder/core/config.js +132 -0
- package/dist/scaffolder/core/config.js.map +1 -0
- package/dist/scaffolder/core/errors.d.ts +37 -0
- package/dist/scaffolder/core/errors.d.ts.map +1 -0
- package/dist/scaffolder/core/errors.js +46 -0
- package/dist/scaffolder/core/errors.js.map +1 -0
- package/dist/scaffolder/core/extend.d.ts +115 -0
- package/dist/scaffolder/core/extend.d.ts.map +1 -0
- package/dist/scaffolder/core/extend.js +116 -0
- package/dist/scaffolder/core/extend.js.map +1 -0
- package/dist/scaffolder/core/materialize.d.ts +71 -0
- package/dist/scaffolder/core/materialize.d.ts.map +1 -0
- package/dist/scaffolder/core/materialize.js +47 -0
- package/dist/scaffolder/core/materialize.js.map +1 -0
- package/dist/scaffolder/core/ports.d.ts +39 -0
- package/dist/scaffolder/core/ports.d.ts.map +1 -0
- package/dist/scaffolder/core/ports.js +33 -0
- package/dist/scaffolder/core/ports.js.map +1 -0
- package/dist/scaffolder/core/three-way-merge.d.ts +113 -0
- package/dist/scaffolder/core/three-way-merge.d.ts.map +1 -0
- package/dist/scaffolder/core/three-way-merge.js +184 -0
- package/dist/scaffolder/core/three-way-merge.js.map +1 -0
- package/dist/scaffolder/index.d.ts +21 -0
- package/dist/scaffolder/index.d.ts.map +1 -0
- package/dist/scaffolder/index.js +20 -0
- package/dist/scaffolder/index.js.map +1 -0
- package/frontend/templates/components/AuthField.vue +68 -0
- package/frontend/templates/i18n/en.json +70 -0
- package/frontend/templates/i18n/nl.json +70 -0
- package/frontend/templates/middleware/auth.ts +25 -0
- package/frontend/templates/middleware/guest.ts +25 -0
- package/frontend/templates/pages/forgot-password.vue +89 -0
- package/frontend/templates/pages/login.vue +90 -0
- package/frontend/templates/pages/logout.vue +46 -0
- package/frontend/templates/pages/register.vue +100 -0
- package/frontend/templates/pages/reset-password.vue +105 -0
- package/frontend/templates/pages/verify-email.vue +76 -0
- package/frontend/templates/plugins/auth.client.ts +111 -0
- package/frontend/templates/runtime.ts +60 -0
- package/package.json +71 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route-guards (het mechanisme). De module levert kant-en-klare guards door de pure route-guards
|
|
3
|
+
* van de frontend auth-kit te composeren/her-exporteren: `authRequiredGuard` (blokkeert anonieme
|
|
4
|
+
* toegang, redirect naar login met terugkeer-parameter) en `guestOnlyGuard` (weert reeds-ingelogde
|
|
5
|
+
* bezoekers, bv. van `/login`). De sessie-status komt via een accessor, de targets via config —
|
|
6
|
+
* geen module-globale state.
|
|
7
|
+
*/
|
|
8
|
+
export { authRequiredGuard, guestOnlyGuard } from '@seifer-webapp-factory/kits/frontend/auth';
|
|
9
|
+
export type { GuardRoute, RedirectTarget, NavigationDecision, NavigationGuard, IsAuthenticated, AuthRequiredGuardOptions, GuestOnlyGuardOptions, } from '@seifer-webapp-factory/kits/frontend/auth';
|
|
10
|
+
//# sourceMappingURL=guards.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.d.ts","sourceRoot":"","sources":["../../../frontend/src/guards.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAC9F,YAAY,EACV,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,2CAA2C,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route-guards (het mechanisme). De module levert kant-en-klare guards door de pure route-guards
|
|
3
|
+
* van de frontend auth-kit te composeren/her-exporteren: `authRequiredGuard` (blokkeert anonieme
|
|
4
|
+
* toegang, redirect naar login met terugkeer-parameter) en `guestOnlyGuard` (weert reeds-ingelogde
|
|
5
|
+
* bezoekers, bv. van `/login`). De sessie-status komt via een accessor, de targets via config —
|
|
6
|
+
* geen module-globale state.
|
|
7
|
+
*/
|
|
8
|
+
export { authRequiredGuard, guestOnlyGuard } from '@seifer-webapp-factory/kits/frontend/auth';
|
|
9
|
+
//# sourceMappingURL=guards.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../../../frontend/src/guards.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* authentication — de frontend-helft (het mechanisme). Barrel die de getypte client, de Vue-
|
|
3
|
+
* composables (provide/inject) en de route-guards bundelt. Alle types leidt de consumer via het
|
|
4
|
+
* contract af; hier alleen het uitvoerbare mechanisme dat de frontend-kits samenbindt.
|
|
5
|
+
*/
|
|
6
|
+
export { createAuthClient, AuthClientError, } from './client.js';
|
|
7
|
+
export type { AuthClient, CreateAuthClientOptions, } from './client.js';
|
|
8
|
+
export { AUTH_CLIENT_KEY, provideAuthClient, useAuthClient, useLogin, useRegister, useVerifyEmail, useForgotPassword, useResetPassword, useLogout, } from './composables.js';
|
|
9
|
+
export type { UseAuthAction } from './composables.js';
|
|
10
|
+
export { authRequiredGuard, guestOnlyGuard, } from './guards.js';
|
|
11
|
+
export type { GuardRoute, RedirectTarget, NavigationDecision, NavigationGuard, IsAuthenticated, AuthRequiredGuardOptions, GuestOnlyGuardOptions, } from './guards.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../frontend/src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,gBAAgB,EAChB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,UAAU,EACV,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACR,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,GACV,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,EACL,iBAAiB,EACjB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,wBAAwB,EACxB,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* authentication — de frontend-helft (het mechanisme). Barrel die de getypte client, de Vue-
|
|
3
|
+
* composables (provide/inject) en de route-guards bundelt. Alle types leidt de consumer via het
|
|
4
|
+
* contract af; hier alleen het uitvoerbare mechanisme dat de frontend-kits samenbindt.
|
|
5
|
+
*/
|
|
6
|
+
export { createAuthClient, AuthClientError, } from './client.js';
|
|
7
|
+
export { AUTH_CLIENT_KEY, provideAuthClient, useAuthClient, useLogin, useRegister, useVerifyEmail, useForgotPassword, useResetPassword, useLogout, } from './composables.js';
|
|
8
|
+
export { authRequiredGuard, guestOnlyGuard, } from './guards.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../frontend/src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,gBAAgB,EAChB,eAAe,GAChB,MAAM,aAAa,CAAC;AAMrB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,aAAa,EACb,QAAQ,EACR,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,gBAAgB,EAChB,SAAS,GACV,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,cAAc,GACf,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* De genormaliseerde vorm van een capability-module-manifest (README.md — spec-sketch, hier getypt).
|
|
3
|
+
* Elke module in deze tier levert een object dat dit interface `satisfies`t.
|
|
4
|
+
*/
|
|
5
|
+
export interface CapabilityModuleManifest {
|
|
6
|
+
/** Stabiele module-slug, bv. 'authentication'. */
|
|
7
|
+
readonly name: string;
|
|
8
|
+
/** Semver van de module (mechanisme + contract samen). */
|
|
9
|
+
readonly version: string;
|
|
10
|
+
/** Versie van de surface-templates, gestempeld in het project bij het genereren. */
|
|
11
|
+
readonly templateVersion: string;
|
|
12
|
+
readonly provides: {
|
|
13
|
+
/** Frontend-pagina-routes die de module oplevert. */
|
|
14
|
+
readonly routes: readonly string[];
|
|
15
|
+
/** Backend-endpoint-paden, afgeleid uit het contract. */
|
|
16
|
+
readonly backendRoutes: readonly string[];
|
|
17
|
+
/** Domein-generieke capabilities die de module aanbiedt. */
|
|
18
|
+
readonly capabilities: readonly string[];
|
|
19
|
+
};
|
|
20
|
+
readonly requires: {
|
|
21
|
+
/** Kits die de host op beide stacks beschikbaar moet hebben. */
|
|
22
|
+
readonly kits: {
|
|
23
|
+
readonly backend: readonly string[];
|
|
24
|
+
readonly frontend: readonly string[];
|
|
25
|
+
};
|
|
26
|
+
/** Requires-ports die de host injecteert (Mailer, UserStore, ...). */
|
|
27
|
+
readonly ports: readonly string[];
|
|
28
|
+
/** Optioneel: andere capability-modules waarvan deze afhangt. */
|
|
29
|
+
readonly modules?: readonly string[];
|
|
30
|
+
};
|
|
31
|
+
/** Pad/ref naar het contract (de seam). */
|
|
32
|
+
readonly contract: string;
|
|
33
|
+
/** Zod-schema-fragment dat de host moet vervullen (nog niet ingevuld in v1). */
|
|
34
|
+
readonly config: unknown;
|
|
35
|
+
/** Backend-migraties die de host draait. */
|
|
36
|
+
readonly migrations: readonly string[];
|
|
37
|
+
/** Globs van bestanden die naar het project worden gematerialiseerd (project-eigen na generate). */
|
|
38
|
+
readonly surface: readonly string[];
|
|
39
|
+
/** Globs van bestanden die een pinned dependency blijven (upstream-eigen, semver-upgrade). */
|
|
40
|
+
readonly mechanism: readonly string[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* De concrete manifest van de authentication-module. `satisfies` geeft compile-time-garantie dat de
|
|
44
|
+
* vorm klopt zonder de letterlijke waarden te verliezen (readonly literals blijven behouden).
|
|
45
|
+
*/
|
|
46
|
+
export declare const authenticationManifest: {
|
|
47
|
+
name: string;
|
|
48
|
+
version: string;
|
|
49
|
+
templateVersion: string;
|
|
50
|
+
provides: {
|
|
51
|
+
routes: string[];
|
|
52
|
+
backendRoutes: readonly string[];
|
|
53
|
+
capabilities: string[];
|
|
54
|
+
};
|
|
55
|
+
requires: {
|
|
56
|
+
kits: {
|
|
57
|
+
backend: string[];
|
|
58
|
+
frontend: string[];
|
|
59
|
+
};
|
|
60
|
+
ports: string[];
|
|
61
|
+
};
|
|
62
|
+
contract: string;
|
|
63
|
+
config: undefined;
|
|
64
|
+
migrations: string[];
|
|
65
|
+
surface: string[];
|
|
66
|
+
mechanism: string[];
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Valideert een capability-module-manifest voordat de scaffolder ermee aan de slag gaat.
|
|
70
|
+
*
|
|
71
|
+
* Controleert (1) dat alle verplichte velden aanwezig en niet-leeg zijn, en (2) dat geen enkele
|
|
72
|
+
* kit-naam dubbel voorkomt BINNEN dezelfde stack (een dubbele kit wijst op een kopieer-fout).
|
|
73
|
+
* Let op: dezelfde slug mag wél op beide stacks staan — 'auth' en 'i18n' bestaan zowel backend
|
|
74
|
+
* als frontend. Gooit een Nederlandstalige fout bij overtreding.
|
|
75
|
+
*
|
|
76
|
+
* @param m het te valideren manifest
|
|
77
|
+
* @returns hetzelfde manifest (zodat je kunt chainen) wanneer het geldig is
|
|
78
|
+
*/
|
|
79
|
+
export declare function validateManifest(m: CapabilityModuleManifest): CapabilityModuleManifest;
|
|
80
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../manifest.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,oFAAoF;IACpF,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE;QACjB,qDAAqD;QACrD,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,yDAAyD;QACzD,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;QAC1C,4DAA4D;QAC5D,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;KAC1C,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE;QACjB,gEAAgE;QAChE,QAAQ,CAAC,IAAI,EAAE;YACb,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;YACpC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;SACtC,CAAC;QACF,sEAAsE;QACtE,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAClC,iEAAiE;QACjE,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;KACtC,CAAC;IACF,2CAA2C;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,gFAAgF;IAChF,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,4CAA4C;IAC5C,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,oGAAoG;IACpG,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAQD;;;GAGG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;CA+BC,CAAC;AAerC;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,wBAAwB,GAAG,wBAAwB,CAyCtF"}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* authentication — de capability-MANIFEST.
|
|
3
|
+
*
|
|
4
|
+
* De machine-leesbare descriptor die de scaffolder leest om de module te assembleren, te wiren en te
|
|
5
|
+
* upgraden (zie capability-modules/README.md, "De capability manifest"). De manifest verklaart:
|
|
6
|
+
* - `provides` — wat de module oplevert (frontend-routes, backend-routes, capabilities),
|
|
7
|
+
* - `requires` — wat de host moet leveren (kits op beide stacks, requires-ports, evt. modules),
|
|
8
|
+
* - `contract` — de seam waaruit beide helften hun types afleiden,
|
|
9
|
+
* - `migrations`— de tabellen die de module bezit,
|
|
10
|
+
* - `surface`/`mechanism` — de expliciete grens tussen project-eigen (gematerialiseerd) en
|
|
11
|
+
* pinned-dependency (upgradet via semver).
|
|
12
|
+
*
|
|
13
|
+
* Bevat GEEN mechanisme: puur een declaratieve beschrijving + een validator.
|
|
14
|
+
*/
|
|
15
|
+
import { AUTH_ENDPOINTS } from './contract/index.js';
|
|
16
|
+
/**
|
|
17
|
+
* De backend-routes worden NIET met de hand overgetypt maar afgeleid uit de contract-endpoint-catalogus,
|
|
18
|
+
* zodat manifest en contract per definitie niet kunnen driften. Elk pad komt precies één keer voor.
|
|
19
|
+
*/
|
|
20
|
+
const backendRoutes = Object.values(AUTH_ENDPOINTS).map((ep) => ep.path);
|
|
21
|
+
/**
|
|
22
|
+
* De concrete manifest van de authentication-module. `satisfies` geeft compile-time-garantie dat de
|
|
23
|
+
* vorm klopt zonder de letterlijke waarden te verliezen (readonly literals blijven behouden).
|
|
24
|
+
*/
|
|
25
|
+
export const authenticationManifest = {
|
|
26
|
+
name: 'authentication',
|
|
27
|
+
version: '0.1.0',
|
|
28
|
+
templateVersion: '0.1.0',
|
|
29
|
+
provides: {
|
|
30
|
+
routes: ['/register', '/login', '/logout', '/verify-email', '/forgot-password', '/reset-password'],
|
|
31
|
+
backendRoutes,
|
|
32
|
+
capabilities: ['user.register', 'user.login', 'session.refresh', 'email.verify', 'password.reset'],
|
|
33
|
+
},
|
|
34
|
+
requires: {
|
|
35
|
+
kits: {
|
|
36
|
+
backend: [
|
|
37
|
+
'auth',
|
|
38
|
+
'access-control',
|
|
39
|
+
'persistence',
|
|
40
|
+
'http-kernel',
|
|
41
|
+
'mailer',
|
|
42
|
+
'config',
|
|
43
|
+
'rate-limit',
|
|
44
|
+
'audit-log',
|
|
45
|
+
'i18n',
|
|
46
|
+
],
|
|
47
|
+
frontend: ['auth', 'http-client', 'forms', 'notifications', 'i18n', 'app-kernel'],
|
|
48
|
+
},
|
|
49
|
+
ports: ['UserStore', 'Mailer', 'Database', 'DesignSystem'],
|
|
50
|
+
},
|
|
51
|
+
contract: './contract/index.ts',
|
|
52
|
+
config: undefined,
|
|
53
|
+
migrations: ['users', 'auth_one_time_tokens'],
|
|
54
|
+
surface: ['backend/templates/**', 'frontend/templates/**'],
|
|
55
|
+
mechanism: ['backend/src/**', 'frontend/src/**', 'contract/**'],
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Zoekt de eerste dubbele waarde in een lijst; geeft `undefined` als alles uniek is.
|
|
59
|
+
* Pure helper — geen module-globale mutable state.
|
|
60
|
+
*/
|
|
61
|
+
function findDuplicate(names) {
|
|
62
|
+
const seen = new Set();
|
|
63
|
+
for (const name of names) {
|
|
64
|
+
if (seen.has(name))
|
|
65
|
+
return name;
|
|
66
|
+
seen.add(name);
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Valideert een capability-module-manifest voordat de scaffolder ermee aan de slag gaat.
|
|
72
|
+
*
|
|
73
|
+
* Controleert (1) dat alle verplichte velden aanwezig en niet-leeg zijn, en (2) dat geen enkele
|
|
74
|
+
* kit-naam dubbel voorkomt BINNEN dezelfde stack (een dubbele kit wijst op een kopieer-fout).
|
|
75
|
+
* Let op: dezelfde slug mag wél op beide stacks staan — 'auth' en 'i18n' bestaan zowel backend
|
|
76
|
+
* als frontend. Gooit een Nederlandstalige fout bij overtreding.
|
|
77
|
+
*
|
|
78
|
+
* @param m het te valideren manifest
|
|
79
|
+
* @returns hetzelfde manifest (zodat je kunt chainen) wanneer het geldig is
|
|
80
|
+
*/
|
|
81
|
+
export function validateManifest(m) {
|
|
82
|
+
if (m.name.trim() === '')
|
|
83
|
+
throw new Error('Manifest ongeldig: "name" mag niet leeg zijn.');
|
|
84
|
+
if (m.version.trim() === '')
|
|
85
|
+
throw new Error('Manifest ongeldig: "version" mag niet leeg zijn.');
|
|
86
|
+
if (m.templateVersion.trim() === '') {
|
|
87
|
+
throw new Error('Manifest ongeldig: "templateVersion" mag niet leeg zijn.');
|
|
88
|
+
}
|
|
89
|
+
if (m.provides.routes.length === 0) {
|
|
90
|
+
throw new Error('Manifest ongeldig: "provides.routes" mag niet leeg zijn.');
|
|
91
|
+
}
|
|
92
|
+
if (m.provides.backendRoutes.length === 0) {
|
|
93
|
+
throw new Error('Manifest ongeldig: "provides.backendRoutes" mag niet leeg zijn.');
|
|
94
|
+
}
|
|
95
|
+
if (m.provides.capabilities.length === 0) {
|
|
96
|
+
throw new Error('Manifest ongeldig: "provides.capabilities" mag niet leeg zijn.');
|
|
97
|
+
}
|
|
98
|
+
if (m.requires.kits.backend.length === 0) {
|
|
99
|
+
throw new Error('Manifest ongeldig: "requires.kits.backend" mag niet leeg zijn.');
|
|
100
|
+
}
|
|
101
|
+
if (m.requires.kits.frontend.length === 0) {
|
|
102
|
+
throw new Error('Manifest ongeldig: "requires.kits.frontend" mag niet leeg zijn.');
|
|
103
|
+
}
|
|
104
|
+
if (m.requires.ports.length === 0) {
|
|
105
|
+
throw new Error('Manifest ongeldig: "requires.ports" mag niet leeg zijn.');
|
|
106
|
+
}
|
|
107
|
+
if (m.contract.trim() === '')
|
|
108
|
+
throw new Error('Manifest ongeldig: "contract" mag niet leeg zijn.');
|
|
109
|
+
if (m.migrations.length === 0) {
|
|
110
|
+
throw new Error('Manifest ongeldig: "migrations" mag niet leeg zijn.');
|
|
111
|
+
}
|
|
112
|
+
if (m.surface.length === 0)
|
|
113
|
+
throw new Error('Manifest ongeldig: "surface" mag niet leeg zijn.');
|
|
114
|
+
if (m.mechanism.length === 0)
|
|
115
|
+
throw new Error('Manifest ongeldig: "mechanism" mag niet leeg zijn.');
|
|
116
|
+
const dubbelBackend = findDuplicate(m.requires.kits.backend);
|
|
117
|
+
if (dubbelBackend !== undefined) {
|
|
118
|
+
throw new Error(`Manifest ongeldig: kit-naam "${dubbelBackend}" komt dubbel voor in requires.kits.backend.`);
|
|
119
|
+
}
|
|
120
|
+
const dubbelFrontend = findDuplicate(m.requires.kits.frontend);
|
|
121
|
+
if (dubbelFrontend !== undefined) {
|
|
122
|
+
throw new Error(`Manifest ongeldig: kit-naam "${dubbelFrontend}" komt dubbel voor in requires.kits.frontend.`);
|
|
123
|
+
}
|
|
124
|
+
return m;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config — niveau 1 van de divergentie-ladder: CONFIGUREREN (US-A1001).
|
|
3
|
+
*
|
|
4
|
+
* `resolveAuthConfig(overrides)` legt de feature-toggles, TTLs, redirects en rate-limits van de
|
|
5
|
+
* auth-module vast over veilige defaults, gevalideerd met zod. Ongeldige waarden falen bij het
|
|
6
|
+
* opstarten met veld + reden (nooit halverwege een flow). Configureren is volledig upgrade-veilig:
|
|
7
|
+
* er wordt niets gematerialiseerd of geëjecteerd.
|
|
8
|
+
*
|
|
9
|
+
* De resolver geeft naast de effectieve config ook terug WELKE surface geraakt wordt: zo laat
|
|
10
|
+
* `emailVerification: false` de verify-pagina/route uit de surface-set vallen (AC1) en `selfRegistration:
|
|
11
|
+
* false` de register-pagina/route. Puur & deterministisch; geen module-globale mutable state.
|
|
12
|
+
*/
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import type { FileDescriptor } from './ports.js';
|
|
15
|
+
/**
|
|
16
|
+
* Het zod-schema voor het config-fragment. Elk veld heeft een default zodat een partieel override
|
|
17
|
+
* geldig is; `.strict()` weigert typefouten in sleutels. De `superRefine` bewaakt de TTL-invariant.
|
|
18
|
+
*/
|
|
19
|
+
export declare const authConfigSchema: z.ZodEffects<z.ZodObject<{
|
|
20
|
+
toggles: z.ZodDefault<z.ZodObject<{
|
|
21
|
+
/** Vereist e-mailverificatie na registratie (drijft de verify-pagina/route). */
|
|
22
|
+
emailVerification: z.ZodDefault<z.ZodBoolean>;
|
|
23
|
+
/** Staat open self-service registratie toe (drijft de register-pagina/route). */
|
|
24
|
+
selfRegistration: z.ZodDefault<z.ZodBoolean>;
|
|
25
|
+
}, "strict", z.ZodTypeAny, {
|
|
26
|
+
emailVerification: boolean;
|
|
27
|
+
selfRegistration: boolean;
|
|
28
|
+
}, {
|
|
29
|
+
emailVerification?: boolean | undefined;
|
|
30
|
+
selfRegistration?: boolean | undefined;
|
|
31
|
+
}>>;
|
|
32
|
+
ttl: z.ZodDefault<z.ZodObject<{
|
|
33
|
+
/** Levensduur van het access-token in seconden. */
|
|
34
|
+
accessSeconds: z.ZodDefault<z.ZodNumber>;
|
|
35
|
+
/** Levensduur van het refresh-token in seconden. */
|
|
36
|
+
refreshSeconds: z.ZodDefault<z.ZodNumber>;
|
|
37
|
+
}, "strict", z.ZodTypeAny, {
|
|
38
|
+
accessSeconds: number;
|
|
39
|
+
refreshSeconds: number;
|
|
40
|
+
}, {
|
|
41
|
+
accessSeconds?: number | undefined;
|
|
42
|
+
refreshSeconds?: number | undefined;
|
|
43
|
+
}>>;
|
|
44
|
+
redirects: z.ZodDefault<z.ZodObject<{
|
|
45
|
+
/** Waar de gebruiker na een geslaagde login landt (absoluut pad). */
|
|
46
|
+
afterLogin: z.ZodDefault<z.ZodString>;
|
|
47
|
+
/** Waar de gebruiker na logout landt (absoluut pad). */
|
|
48
|
+
afterLogout: z.ZodDefault<z.ZodString>;
|
|
49
|
+
}, "strict", z.ZodTypeAny, {
|
|
50
|
+
afterLogin: string;
|
|
51
|
+
afterLogout: string;
|
|
52
|
+
}, {
|
|
53
|
+
afterLogin?: string | undefined;
|
|
54
|
+
afterLogout?: string | undefined;
|
|
55
|
+
}>>;
|
|
56
|
+
rateLimit: z.ZodDefault<z.ZodObject<{
|
|
57
|
+
login: z.ZodDefault<z.ZodObject<{
|
|
58
|
+
max: z.ZodDefault<z.ZodNumber>;
|
|
59
|
+
windowSeconds: z.ZodDefault<z.ZodNumber>;
|
|
60
|
+
}, "strict", z.ZodTypeAny, {
|
|
61
|
+
max: number;
|
|
62
|
+
windowSeconds: number;
|
|
63
|
+
}, {
|
|
64
|
+
max?: number | undefined;
|
|
65
|
+
windowSeconds?: number | undefined;
|
|
66
|
+
}>>;
|
|
67
|
+
forgotPassword: z.ZodDefault<z.ZodObject<{
|
|
68
|
+
max: z.ZodDefault<z.ZodNumber>;
|
|
69
|
+
windowSeconds: z.ZodDefault<z.ZodNumber>;
|
|
70
|
+
}, "strict", z.ZodTypeAny, {
|
|
71
|
+
max: number;
|
|
72
|
+
windowSeconds: number;
|
|
73
|
+
}, {
|
|
74
|
+
max?: number | undefined;
|
|
75
|
+
windowSeconds?: number | undefined;
|
|
76
|
+
}>>;
|
|
77
|
+
}, "strict", z.ZodTypeAny, {
|
|
78
|
+
login: {
|
|
79
|
+
max: number;
|
|
80
|
+
windowSeconds: number;
|
|
81
|
+
};
|
|
82
|
+
forgotPassword: {
|
|
83
|
+
max: number;
|
|
84
|
+
windowSeconds: number;
|
|
85
|
+
};
|
|
86
|
+
}, {
|
|
87
|
+
login?: {
|
|
88
|
+
max?: number | undefined;
|
|
89
|
+
windowSeconds?: number | undefined;
|
|
90
|
+
} | undefined;
|
|
91
|
+
forgotPassword?: {
|
|
92
|
+
max?: number | undefined;
|
|
93
|
+
windowSeconds?: number | undefined;
|
|
94
|
+
} | undefined;
|
|
95
|
+
}>>;
|
|
96
|
+
}, "strict", z.ZodTypeAny, {
|
|
97
|
+
toggles: {
|
|
98
|
+
emailVerification: boolean;
|
|
99
|
+
selfRegistration: boolean;
|
|
100
|
+
};
|
|
101
|
+
ttl: {
|
|
102
|
+
accessSeconds: number;
|
|
103
|
+
refreshSeconds: number;
|
|
104
|
+
};
|
|
105
|
+
redirects: {
|
|
106
|
+
afterLogin: string;
|
|
107
|
+
afterLogout: string;
|
|
108
|
+
};
|
|
109
|
+
rateLimit: {
|
|
110
|
+
login: {
|
|
111
|
+
max: number;
|
|
112
|
+
windowSeconds: number;
|
|
113
|
+
};
|
|
114
|
+
forgotPassword: {
|
|
115
|
+
max: number;
|
|
116
|
+
windowSeconds: number;
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
}, {
|
|
120
|
+
toggles?: {
|
|
121
|
+
emailVerification?: boolean | undefined;
|
|
122
|
+
selfRegistration?: boolean | undefined;
|
|
123
|
+
} | undefined;
|
|
124
|
+
ttl?: {
|
|
125
|
+
accessSeconds?: number | undefined;
|
|
126
|
+
refreshSeconds?: number | undefined;
|
|
127
|
+
} | undefined;
|
|
128
|
+
redirects?: {
|
|
129
|
+
afterLogin?: string | undefined;
|
|
130
|
+
afterLogout?: string | undefined;
|
|
131
|
+
} | undefined;
|
|
132
|
+
rateLimit?: {
|
|
133
|
+
login?: {
|
|
134
|
+
max?: number | undefined;
|
|
135
|
+
windowSeconds?: number | undefined;
|
|
136
|
+
} | undefined;
|
|
137
|
+
forgotPassword?: {
|
|
138
|
+
max?: number | undefined;
|
|
139
|
+
windowSeconds?: number | undefined;
|
|
140
|
+
} | undefined;
|
|
141
|
+
} | undefined;
|
|
142
|
+
}>, {
|
|
143
|
+
toggles: {
|
|
144
|
+
emailVerification: boolean;
|
|
145
|
+
selfRegistration: boolean;
|
|
146
|
+
};
|
|
147
|
+
ttl: {
|
|
148
|
+
accessSeconds: number;
|
|
149
|
+
refreshSeconds: number;
|
|
150
|
+
};
|
|
151
|
+
redirects: {
|
|
152
|
+
afterLogin: string;
|
|
153
|
+
afterLogout: string;
|
|
154
|
+
};
|
|
155
|
+
rateLimit: {
|
|
156
|
+
login: {
|
|
157
|
+
max: number;
|
|
158
|
+
windowSeconds: number;
|
|
159
|
+
};
|
|
160
|
+
forgotPassword: {
|
|
161
|
+
max: number;
|
|
162
|
+
windowSeconds: number;
|
|
163
|
+
};
|
|
164
|
+
};
|
|
165
|
+
}, {
|
|
166
|
+
toggles?: {
|
|
167
|
+
emailVerification?: boolean | undefined;
|
|
168
|
+
selfRegistration?: boolean | undefined;
|
|
169
|
+
} | undefined;
|
|
170
|
+
ttl?: {
|
|
171
|
+
accessSeconds?: number | undefined;
|
|
172
|
+
refreshSeconds?: number | undefined;
|
|
173
|
+
} | undefined;
|
|
174
|
+
redirects?: {
|
|
175
|
+
afterLogin?: string | undefined;
|
|
176
|
+
afterLogout?: string | undefined;
|
|
177
|
+
} | undefined;
|
|
178
|
+
rateLimit?: {
|
|
179
|
+
login?: {
|
|
180
|
+
max?: number | undefined;
|
|
181
|
+
windowSeconds?: number | undefined;
|
|
182
|
+
} | undefined;
|
|
183
|
+
forgotPassword?: {
|
|
184
|
+
max?: number | undefined;
|
|
185
|
+
windowSeconds?: number | undefined;
|
|
186
|
+
} | undefined;
|
|
187
|
+
} | undefined;
|
|
188
|
+
}>;
|
|
189
|
+
/** De effectieve, gevalideerde auth-config (output-type met defaults toegepast). */
|
|
190
|
+
export type EffectiveAuthConfig = z.infer<typeof authConfigSchema>;
|
|
191
|
+
/** De surface/routes die door de config uit de set vallen. */
|
|
192
|
+
export interface AffectedSurface {
|
|
193
|
+
readonly removedRoutes: readonly string[];
|
|
194
|
+
readonly removedBackendRoutes: readonly string[];
|
|
195
|
+
readonly removedFiles: readonly string[];
|
|
196
|
+
}
|
|
197
|
+
/** Resultaat van `resolveAuthConfig`: de effectieve config + de geraakte surface. */
|
|
198
|
+
export interface ResolvedAuthConfig {
|
|
199
|
+
readonly config: EffectiveAuthConfig;
|
|
200
|
+
readonly affected: AffectedSurface;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Valideert en resolveet het config-fragment over de defaults.
|
|
204
|
+
*
|
|
205
|
+
* @throws AuthConfigValidationError met veld + reden bij ongeldige/incompatibele waarden
|
|
206
|
+
*/
|
|
207
|
+
export declare function resolveAuthConfig(overrides?: unknown): ResolvedAuthConfig;
|
|
208
|
+
/**
|
|
209
|
+
* Filtert een surface-set aan de hand van de geresolvede config: bestanden die door een uitgezette
|
|
210
|
+
* toggle wegvallen, worden uit de te materialiseren set verwijderd (bv. de verify-pagina). Pure functie.
|
|
211
|
+
*/
|
|
212
|
+
export declare function filterSurfaceByConfig(surfaceFiles: readonly FileDescriptor[], resolved: ResolvedAuthConfig): FileDescriptor[];
|
|
213
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../scaffolder/core/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;QAIrB,gFAAgF;;QAEhF,iFAAiF;;;;;;;;;;QAOjF,mDAAmD;;QAEnD,oDAAoD;;;;;;;;;;QAOpD,qEAAqE;;QAErE,wDAAwD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0B5D,CAAC;AAaL,oFAAoF;AACpF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAuBnE,8DAA8D;AAC9D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,oBAAoB,EAAE,SAAS,MAAM,EAAE,CAAC;IACjD,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,qFAAqF;AACrF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;CACpC;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,kBAAkB,CA2BzE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,YAAY,EAAE,SAAS,cAAc,EAAE,EACvC,QAAQ,EAAE,kBAAkB,GAC3B,cAAc,EAAE,CAGlB"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* config — niveau 1 van de divergentie-ladder: CONFIGUREREN (US-A1001).
|
|
3
|
+
*
|
|
4
|
+
* `resolveAuthConfig(overrides)` legt de feature-toggles, TTLs, redirects en rate-limits van de
|
|
5
|
+
* auth-module vast over veilige defaults, gevalideerd met zod. Ongeldige waarden falen bij het
|
|
6
|
+
* opstarten met veld + reden (nooit halverwege een flow). Configureren is volledig upgrade-veilig:
|
|
7
|
+
* er wordt niets gematerialiseerd of geëjecteerd.
|
|
8
|
+
*
|
|
9
|
+
* De resolver geeft naast de effectieve config ook terug WELKE surface geraakt wordt: zo laat
|
|
10
|
+
* `emailVerification: false` de verify-pagina/route uit de surface-set vallen (AC1) en `selfRegistration:
|
|
11
|
+
* false` de register-pagina/route. Puur & deterministisch; geen module-globale mutable state.
|
|
12
|
+
*/
|
|
13
|
+
import { z } from 'zod';
|
|
14
|
+
import { AuthConfigValidationError } from './errors.js';
|
|
15
|
+
/**
|
|
16
|
+
* Het zod-schema voor het config-fragment. Elk veld heeft een default zodat een partieel override
|
|
17
|
+
* geldig is; `.strict()` weigert typefouten in sleutels. De `superRefine` bewaakt de TTL-invariant.
|
|
18
|
+
*/
|
|
19
|
+
export const authConfigSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
toggles: z
|
|
22
|
+
.object({
|
|
23
|
+
/** Vereist e-mailverificatie na registratie (drijft de verify-pagina/route). */
|
|
24
|
+
emailVerification: z.boolean().default(true),
|
|
25
|
+
/** Staat open self-service registratie toe (drijft de register-pagina/route). */
|
|
26
|
+
selfRegistration: z.boolean().default(true),
|
|
27
|
+
})
|
|
28
|
+
.strict()
|
|
29
|
+
.default({}),
|
|
30
|
+
ttl: z
|
|
31
|
+
.object({
|
|
32
|
+
/** Levensduur van het access-token in seconden. */
|
|
33
|
+
accessSeconds: z.number().int().positive().default(900),
|
|
34
|
+
/** Levensduur van het refresh-token in seconden. */
|
|
35
|
+
refreshSeconds: z.number().int().positive().default(60 * 60 * 24 * 14),
|
|
36
|
+
})
|
|
37
|
+
.strict()
|
|
38
|
+
.default({}),
|
|
39
|
+
redirects: z
|
|
40
|
+
.object({
|
|
41
|
+
/** Waar de gebruiker na een geslaagde login landt (absoluut pad). */
|
|
42
|
+
afterLogin: z.string().startsWith('/', 'Redirect moet een absoluut pad zijn (begint met /).').default('/'),
|
|
43
|
+
/** Waar de gebruiker na logout landt (absoluut pad). */
|
|
44
|
+
afterLogout: z
|
|
45
|
+
.string()
|
|
46
|
+
.startsWith('/', 'Redirect moet een absoluut pad zijn (begint met /).')
|
|
47
|
+
.default('/login'),
|
|
48
|
+
})
|
|
49
|
+
.strict()
|
|
50
|
+
.default({}),
|
|
51
|
+
rateLimit: z
|
|
52
|
+
.object({
|
|
53
|
+
login: rateWindow(5, 15 * 60),
|
|
54
|
+
forgotPassword: rateWindow(3, 60 * 60),
|
|
55
|
+
})
|
|
56
|
+
.strict()
|
|
57
|
+
.default({}),
|
|
58
|
+
})
|
|
59
|
+
.strict()
|
|
60
|
+
.superRefine((cfg, ctx) => {
|
|
61
|
+
// Access moet vóór refresh verlopen — anders kan de stille refresh nooit een korter access-token vervangen.
|
|
62
|
+
if (cfg.ttl.accessSeconds >= cfg.ttl.refreshSeconds) {
|
|
63
|
+
ctx.addIssue({
|
|
64
|
+
code: z.ZodIssueCode.custom,
|
|
65
|
+
path: ['ttl', 'refreshSeconds'],
|
|
66
|
+
message: 'refreshSeconds moet groter zijn dan accessSeconds.',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
/** Een rate-limit-venster (max pogingen binnen een tijdvenster). Helper voor het schema hierboven. */
|
|
71
|
+
function rateWindow(defaultMax, defaultWindow) {
|
|
72
|
+
return z
|
|
73
|
+
.object({
|
|
74
|
+
max: z.number().int().positive().default(defaultMax),
|
|
75
|
+
windowSeconds: z.number().int().positive().default(defaultWindow),
|
|
76
|
+
})
|
|
77
|
+
.strict()
|
|
78
|
+
.default({});
|
|
79
|
+
}
|
|
80
|
+
/** Wat er uit de surface valt als `emailVerification` uit staat. */
|
|
81
|
+
const EMAIL_VERIFICATION_IMPACT = {
|
|
82
|
+
routes: ['/verify-email'],
|
|
83
|
+
backendRoutes: ['/auth/verify-email'],
|
|
84
|
+
files: ['frontend/templates/pages/verify-email.vue'],
|
|
85
|
+
};
|
|
86
|
+
/** Wat er uit de surface valt als `selfRegistration` uit staat. */
|
|
87
|
+
const SELF_REGISTRATION_IMPACT = {
|
|
88
|
+
routes: ['/register'],
|
|
89
|
+
backendRoutes: ['/auth/register'],
|
|
90
|
+
files: ['frontend/templates/pages/register.vue'],
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Valideert en resolveet het config-fragment over de defaults.
|
|
94
|
+
*
|
|
95
|
+
* @throws AuthConfigValidationError met veld + reden bij ongeldige/incompatibele waarden
|
|
96
|
+
*/
|
|
97
|
+
export function resolveAuthConfig(overrides) {
|
|
98
|
+
const result = authConfigSchema.safeParse(overrides ?? {});
|
|
99
|
+
if (!result.success) {
|
|
100
|
+
const violations = result.error.issues.map((issue) => ({
|
|
101
|
+
path: issue.path.length > 0 ? issue.path.join('.') : '(root)',
|
|
102
|
+
message: issue.message,
|
|
103
|
+
}));
|
|
104
|
+
throw new AuthConfigValidationError(violations);
|
|
105
|
+
}
|
|
106
|
+
const config = result.data;
|
|
107
|
+
const removedRoutes = [];
|
|
108
|
+
const removedBackendRoutes = [];
|
|
109
|
+
const removedFiles = [];
|
|
110
|
+
const drop = (impact) => {
|
|
111
|
+
removedRoutes.push(...impact.routes);
|
|
112
|
+
removedBackendRoutes.push(...impact.backendRoutes);
|
|
113
|
+
removedFiles.push(...impact.files);
|
|
114
|
+
};
|
|
115
|
+
if (!config.toggles.emailVerification)
|
|
116
|
+
drop(EMAIL_VERIFICATION_IMPACT);
|
|
117
|
+
if (!config.toggles.selfRegistration)
|
|
118
|
+
drop(SELF_REGISTRATION_IMPACT);
|
|
119
|
+
return {
|
|
120
|
+
config,
|
|
121
|
+
affected: { removedRoutes, removedBackendRoutes, removedFiles },
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Filtert een surface-set aan de hand van de geresolvede config: bestanden die door een uitgezette
|
|
126
|
+
* toggle wegvallen, worden uit de te materialiseren set verwijderd (bv. de verify-pagina). Pure functie.
|
|
127
|
+
*/
|
|
128
|
+
export function filterSurfaceByConfig(surfaceFiles, resolved) {
|
|
129
|
+
const removed = new Set(resolved.affected.removedFiles);
|
|
130
|
+
return surfaceFiles.filter((file) => !removed.has(file.path));
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../scaffolder/core/config.ts"],"names":[],"mappings":"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"}
|