diff --git a/apps/app/.eslintrc.cjs b/apps/app/.eslintrc.cjs index 75d33856..fb2dc4b2 100644 --- a/apps/app/.eslintrc.cjs +++ b/apps/app/.eslintrc.cjs @@ -208,26 +208,45 @@ module.exports = { // The `lib → stores` edge is intentionally disallowed; lib/axios.ts // uses dynamic `await import('@/stores/...')` for its 4 store reads // so the static-import surface stays clean. - // Sub-zone enforcement (components/{organizer,portal,shared}) is a - // backlog item (TECH-WS3-BOUNDARIES-SUBZONES); it lands after the - // §4.2 consolidation directory layout. + // + // WS-3 PR-B1 activated TECH-WS3-BOUNDARIES-SUBZONES: components and + // pages now have organizer/portal/shared sub-zones (§4.2 charter). + // The cross-context edges (organizer ↛ portal, shared ↛ portal/organizer) + // are forbidden so a future portal-only refactor cannot leak into + // the organizer surface and vice versa. + // // FORWARD-FLAG: when src/plugins/1.router/ migrates to src/router/ - // in a later WS-3 PR, add `{ type: 'router', pattern: 'src/router/**' }` - // to boundaries/elements and `{ from: 'router', allow: ['types', - // 'utils', 'lib', 'plugins', 'stores'] }` to the rules. + // in a later WS-3 PR (TECH-WS3-BOUNDARIES-ROUTER-ZONE), add + // `{ type: 'router', pattern: 'src/router/**' }` to boundaries/elements + // and `{ from: 'router', allow: ['types', 'utils', 'lib', 'plugins', + // 'stores'] }` to the rules. 'boundaries/element-types': ['error', { default: 'disallow', rules: [ { from: 'types', allow: ['types'] }, { from: 'utils', allow: ['types', 'utils'] }, { from: 'lib', allow: ['types', 'utils', 'lib'] }, - { from: 'plugins', allow: ['types', 'utils', 'lib', 'plugins', 'stores'] }, - { from: 'composables', allow: ['types', 'utils', 'lib', 'composables', 'stores'] }, - { from: 'stores', allow: ['types', 'utils', 'lib', 'composables', 'stores'] }, + { from: 'plugins', allow: ['types', 'utils', 'lib', 'plugins', 'stores', 'stores-portal'] }, + { from: 'composables-forms', allow: ['types', 'utils', 'lib', 'composables-forms'] }, + { from: 'composables', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores', 'stores-portal'] }, + { from: 'stores-portal', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores', 'stores-portal'] }, + { from: 'stores', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores'] }, { from: 'navigation', allow: ['types', 'utils', 'navigation'] }, - { from: 'components', allow: ['types', 'utils', 'lib', 'composables', 'stores', 'components'] }, - { from: 'layouts', allow: ['types', 'utils', 'lib', 'composables', 'stores', 'navigation', 'components', 'layouts'] }, - { from: 'pages', allow: ['types', 'utils', 'lib', 'composables', 'stores', 'navigation', 'components', 'layouts'] }, + { from: 'components-shared', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'components-shared'] }, + { from: 'components-portal', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores', 'stores-portal', 'components-shared', 'components-portal'] }, + { from: 'components-organizer', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores', 'components-shared', 'components-organizer'] }, + { from: 'components', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores', 'components', 'components-shared', 'components-organizer'] }, + { from: 'layouts', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores', 'stores-portal', 'navigation', 'components', 'components-shared', 'components-portal', 'components-organizer', 'layouts'] }, + + // success.vue conditionally enriches with the portal auth user + // ("Welcome back, X") when authenticated. The page is still public- + // accessible; the store read is optional. PR-B2 cleanup may move + // success.vue into pages-portal so this exception can drop. + { from: 'pages-register', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'plugins', 'components-shared', 'stores-portal', 'layouts'] }, + { from: 'pages-portal', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores', 'stores-portal', 'navigation', 'components-shared', 'components-portal', 'layouts', 'plugins'] }, + { from: 'pages-organizer', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores', 'navigation', 'components', 'components-shared', 'components-organizer', 'layouts', 'plugins'] }, + { from: 'pages-platform', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores', 'navigation', 'components', 'components-shared', 'components-organizer', 'layouts', 'plugins'] }, + { from: 'pages', allow: ['types', 'utils', 'lib', 'composables', 'composables-forms', 'stores', 'stores-portal', 'navigation', 'components', 'components-shared', 'components-portal', 'components-organizer', 'layouts'] }, ], }], 'boundaries/no-unknown': 'off', // External packages are fine. @@ -239,17 +258,33 @@ module.exports = { typescript: {}, }, - // Element-type assignment: first-match-wins. Order matters. + // Element-type assignment: first-match-wins. Order matters — narrower + // sub-zones declared before their broader parents. 'boundaries/elements': [ { type: 'types', pattern: 'src/types/**' }, { type: 'utils', pattern: 'src/utils/**' }, { type: 'lib', pattern: 'src/lib/**' }, { type: 'plugins', pattern: 'src/plugins/**' }, + { type: 'composables-forms', pattern: 'src/composables/forms/**' }, { type: 'composables', pattern: 'src/composables/**' }, + { type: 'stores-portal', pattern: 'src/stores/portal/**' }, { type: 'stores', pattern: 'src/stores/**' }, { type: 'navigation', pattern: 'src/navigation/**' }, + + // components/shared/** is the canonical sub-zone. components/auth/** + // and components/settings/** are folded in here as legacy cross-context + // siblings (MFA dialogs + password-requirements widgets used by both + // organizer reset-password and portal wachtwoord-instellen / profiel + // flows). PR-B2 may rehome these under components/shared/{auth,settings}/. + { type: 'components-shared', pattern: 'src/components/{shared,auth,settings}/**' }, + { type: 'components-portal', pattern: 'src/components/portal/**' }, + { type: 'components-organizer', pattern: 'src/components/organizer/**' }, { type: 'components', pattern: 'src/components/**' }, { type: 'layouts', pattern: 'src/layouts/**' }, + { type: 'pages-register', pattern: 'src/pages/register/**' }, + { type: 'pages-portal', pattern: 'src/pages/portal/**' }, + { type: 'pages-platform', pattern: 'src/pages/platform/**' }, + { type: 'pages-organizer', pattern: 'src/pages/{events,members,organisation,account-settings,dashboard,invitations}/**' }, { type: 'pages', pattern: 'src/pages/**' }, ], 'boundaries/ignore': [