Young's Mind
Research

Stages doc — the security section re-introduces four corrected errors

Verified: prod-implementation-stages-2026-10-18.md §"Security layer" and §"Current state", against live prod and Medusa's own docs.

Stages doc — the security section re-introduces four corrected errors

Verified: prod-implementation-stages-2026-10-18.md §"Security layer" and §"Current state", against live prod and Medusa's own docs.

The "Current state" section is accurate — I re-measured every claim on 161.33.71.67 and all six hold (Docker 29.7.2 / 0 containers; 3 nginx vhosts; solos-docs + pulse-site active; sol decommissioned; tailscaled inactive; :8012 not listening; Authelia absent). Credit where due.

The security section, however, is a regression. It restates four claims I corrected earlier today in 2fa-and-account-management.md. The corrections did not propagate. Each is repeated below with the evidence, so the stages doc can be fixed at source.


1. 🔴 "RBAC (admin/staff/read-only)" — paid Enterprise, not available

Stages doc, §Account management: [ ] RBAC (admin/staff/read-only) — listed as a plain task.

Medusa's ENTERPRISE-LICENSE.md is explicit: "RBAC (role-based access control) and SSO (single sign-on) are Medusa Enterprise Edition features."4 The proprietary paths include the RBAC module, its admin APIs, and the roles/policies dashboard routes.4 The licence adds that enabling an Enterprise feature flag "constitutes a representation that you hold a valid commercial agreement", and that circumventing the gate is itself a violation.4

This is not a task that can be completed. It is either (a) removed from the pilot scope, or (b) converted to a licence procurement item — "contact sales", so the cost is genuinely unknown, not zero. A checkbox implies a build; there is no build to do.


2. 🔴 "Audit log (who/what/when)" — not found in the MIT product

Stages doc, §Account management: [ ] Audit log (who/what/when).

I read the complete Medusa Admin Settings index — the authoritative list of what the admin actually exposes. It contains no audit-log, activity-log, or session entry: Store, Users, Regions, Tax Regions, Return Reasons, Refund Reasons, Sales Channels, Product Types, Product Tags, Locations & Shipping, Search, Publishable API Keys, Secret API Keys, Workflow Executions, Profile.2

So there is no admin audit log to enable. Tam's Authelia doc claims audit for L1 — a different surface, and that one is credible. For L2 (Medusa), the audit log is not a checkbox — it is a build, or it does not exist.

What is observable: Medusa emits events — the MFA docs name auth.mfa_disabled and auth.mfa_recovery_codes_generated.1 A subscriber could persist those into our own audit table. That is a real design option, but it is a build item, not an enablement.


3. 🔴 "Session management (list + revoke)" — not in the admin

Stages doc, §Account management: [ ] Session management (list + revoke).

Same evidence as §2: the Settings index has no session surface.2 Medusa Admin cannot list or revoke a user's active sessions.

Consequence for the security story: our pitch says "sign out everywhere" and "staff log in with real accounts." The "sign out everywhere" half is not shipped by Medusa. If we promise it, we build it. If we don't, we must not put it in the sales copy. Nova's 2FA UX work assumed this screen exists — it does not.


4. 🔴 "Recovery codes generated at provisioning" — wrong actor, wrong time

Stages doc, §L2: [ ] Recovery codes generated at provisioning.

Medusa's MFA docs specify the actual flow:1

  • Recovery codes require the user to already have at least one enabled MFA factor, and the user must be authenticated to generate them.1
  • Generation is a user-initiated call to POST /auth/mfa/recovery-codes.1
  • The default count is 10, configurable via mfa.recovery_code_count.1
  • Generating a new set replaces the previous ones and emits auth.mfa_recovery_codes_generated.1
  • Each code is single-use; once consumed it cannot be reused.1

So recovery codes cannot be generated at provisioning — they are generated by the user, after enrolment, from an authenticated session. The provisioning script can prompt and verify that the user has done it, but it cannot do it for them (and should not: a recovery code we hold is a recovery code an attacker can ask us for).

The right provisioning step is a gate, not a generation: "admin has enrolled TOTP and generated recovery codes before the tenant is marked live."


5. ⚠️ "EVE templates carry Better Auth 2FA plugin" — the template ships Better Auth, not 2FA

Stages doc, §L3: [ ] EVE templates carry Better Auth 2FA plugin / [ ] TOTP for EVE admin/receptionist accounts.

What the catalogue actually says: the eve Web Chat Agent template ships "per-user long-term memory, Better Auth, Drizzle, Neon, and Upstash Redis."6 Better Auth is present — the 2FA plugin is not claimed.

Better Auth's 2FA is an opt-in plugin: you add twoFactor() to the auth config and run a migration to create its tables.5 It is not on by default.

So the accurate statement is: the EVE template gives us Better Auth, and Better Auth supports TOTP 2FA once we add and migrate the plugin. That is small work — but it is work, and "carries the 2FA plugin" overstates it. Given our own rule about docstrings claiming capabilities nothing performs, this distinction matters.


6. What the stages doc gets right (and should keep)

  • §L1 Authelia — correct, and matches Tam's design.authelia-optimization
  • "AUTH_MFA_ENCRYPTION_KEY set per tenant" — correct, and the one env var Medusa needs.1
  • "TOTP required for admin accounts" — correct in intent; make it a gate (see §4), and add disable_policy: challenge so a stolen session cannot remove the factor.1
  • §"Current state" — measured, accurate, all six claims verified.
ItemChange
RBAC (admin/staff/read-only)→ REMOVE from pilot. Add to a licence-procurement list (cost unknown).
Audit log (who/what/when)→ not a checkbox. Either build an event-subscriber audit table, or drop the claim.
Session management (list + revoke)→ not shipped. Build, or remove from the promise and from Nova's UX scope.
Recovery codes generated at provisioning→ "gate: admin has enrolled TOTP + generated recovery codes before go-live" (user-generated, not provisioned).
EVE templates carry Better Auth 2FA plugin→ "EVE template ships Better Auth; 2FA is an opt-in plugin to add + migrate".

Also worth adding to §L2 (from the same MFA doc):1

  • disable_policy: challenge — requires re-verification before MFA removal.
  • requireMfa: { maxAgeSeconds: N } — a recent challenge for elevated writes (refunds, bulk pricing). This strengthens F7's HIL gate with a second control.

Honest limits

  • I read the documentation and the licence file, not a running Medusa Admin. I did not click through a live Settings panel — the absence of sessions/audit/roles is established from the published Settings index, which is the vendor's own complete list.2
  • "Not found in the docs" is not proof of absence in the code. Medusa is open-source; a session-management or audit surface could exist un-documented. I am reporting it as not found and not promised, which is the safe direction for a scoping decision — but if someone greps the admin source and finds it, I am wrong and should be corrected.
  • I did not verify the EVE template's actual package.json — the Better Auth claim is the catalogue description,6 and the plugin-opt-in detail is Better Auth's own docs.5 The two together are strong but not a repo read.
  • The Enterprise licence price is unknown ("contact sales").

Sources

Sources

1 https://docs.medusajs.com/resources/commerce-modules/auth/mfa — Medusa — MFA (Auth Module): recovery codes, disable_policy, requireMfa 2 https://docs.medusajs.com/user-guide/settings — Medusa — Admin Settings index (what exists) 4 https://raw.githubusercontent.com/medusajs/medusa/develop/ENTERPRISE-LICENSE.md — Medusa — Enterprise License (RBAC + SSO proprietary) 5 https://better-auth.com/docs/plugins/2fa — Better Auth — 2FA plugin (opt-in registration) 6 https://eve.dev/templates — eve — Templates catalogue

Copyright © 2026