MemberJunction / MemberJunction/MJ

Two more shipped defaults name a system user that does not exist on a stock database

Open
#4,232 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TSQL
Stars
29
Forks
6
Avg merge
2d 1h
Merged PRs (30d)
323

Description

**Found by** the PR gauntlet on #4231 (`fix/4209-provisioning-context-user`), 2026-09-04. Not caused by that PR: verified pre-existing at `938cd9e9e8f9425924dc7d7bd3b55c90dfd90e46`.

### Where
`packages/MJServer/src/config.ts:149` and `:165` — the zod schemas for `scheduledJobs` and
`integrationSyncWorker`. Consumers: `packages/MJServer/src/services/ScheduledJobsService.ts:137`
and `packages/MJServer/src/services/IntegrationSyncWorkerService.ts:50`.

### What happens
Both schemas declare `systemUserEmail: z.string().optional().default('system@memberjunction.org')`.
No `__mj.User` row carries that address on a stock database — the seeded system user is
`not.set@nowhere.com`. The same two keys are ALSO given a value in `DEFAULT_SERVER_CONFIG`
(`config.ts:723` and `:732`), where they are `'not.set@nowhere.com'`.

Two defaults for one setting, disagreeing, one of them unresolvable. It is masked only because
`DEFAULT_SERVER_CONFIG` is the merge base, so it always supplies the key and the zod default can
never fire.

### Why it matters
This is the same class of defect as #4209 — a shipped default naming a user that cannot exist —
sitting one refactor away from firing. Anyone who tidies the duplicated keys out of
`DEFAULT_SERVER_CONFIG` (a reasonable cleanup: the zod schema is where defaults belong) turns on
a latent failure with no test to catch it. `ScheduledJobsService.ts:41` then throws
`System user not found with email: system@memberjunction.org` at startup, and the integration
sync worker logs and does nothing.

### Repro
```bash
# Remove the systemUserEmail key from the scheduledJobs block of DEFAULT_SERVER_CONFIG
# (packages/MJServer/src/config.ts:723), rebuild, and boot MJAPI.
cd packages/MJServer && pnpm run build
cd ../MJAPI && pnpm start
# => Error: System user not found with email: system@memberjunction.org
```

### Evidence
Live workspace database (`MJ_ATS_Dev`), `SELECT ID, Name, Email FROM __mj.vwUsers` — 7 rows, no
`system@memberjunction.org`. The seeded system user is
`ECAFCCEC-6A37-EF11-86D4-000D3A4E707E / System / not.set@nowhere.com`.

### Suggested fix
Delete the two zod `.default(...)` values so `DEFAULT_SERVER_CONFIG` is the single source of the
default, or make them agree with it. **Better:** route both services through
`ResolveConfiguredPrincipal(candidate, 'ScheduledJobs' | 'IntegrationSyncWorker')` from
`packages/MJServer/src/auth/principals.ts` (exported from the package index as of #4231). They are
the same "act as a config-named user" problem that module now owns, and adopting it also gives
them the `Name` rung and the deterministic active-principal fallback for free.

### Definition of done
- [ ] A failing test that reproduces it, then green
- [ ] One default per setting, and it resolves on a stock database
- [ ] Existing suite and gates green; no changed expectation in an existing test

### Verify by
`cd packages/MJServer && pnpm test`, then boot MJAPI with no `scheduledJobs` block in
`mj.config.cjs` and confirm the scheduled-jobs engine resolves a system user and starts.

Contributor guide

Open the contributing guide

Research direction

Start with the zod schemas and DEFAULT_SERVER_CONFIG in packages/MJServer/src/config.ts, then read ScheduledJobsService.ts, IntegrationSyncWorkerService.ts, and principals.ts. Add a regression test covering a stock database and run `cd packages/MJServer && pnpm test`. Done means each setting has one resolvable default, both services resolve a system user, and MJAPI starts without a scheduledJobs block.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, databases, testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
74/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.