Skip to main content

Auth live test protocol — 2026-07-28

Automated run of the live auth suite (tests/live/). Case IDs refer to docs/testing/auth-test-plan.md.

Run header

ItemValue
Date2026-07-28
Run idms4db7o4-ee22
Backendhttps://backdev.enode.ai/api
Commit6f947b7 (dirty)
Nodev24.1.0
Preflightfixed OTP proven for register+login+delete; unknown-email login reason: login; debug abort/314 → 401
FixtureslegacyPro: ✓ · legacyOne: — · oneTier: ✓ · proPlus: ✓ · socialCollision: ✓

Results

CaseLayerTestResultms
AUTH-LOG-01LAUTH-LOG-01 pro_app: login-OTP request for an existing Pro user → reason login269
AUTH-LOG-01, AUTH-LOG-02LAUTH-LOG-02 pro_app: the fixed OTP logs in; the token authenticates and carries privileges398
AUTH-LOG-01LAUTH-LOG-01/02 portal: request + verify succeed under the portal flavor418
AUTH-LOG-03LAUTH-LOG-03 a wrong OTP on verify is rejected (4xx recorded)234
AUTH-LOG-03, AUTH-LOG-04LAUTH-LOG-04 three wrong attempts; the session outcome afterwards is recorded513
AUTH-LOG-05LAUTH-LOG-05 resend answers 200 and the code still verifies507
AUTH-LOG-06LAUTH-LOG-06 login-OTP request for a never-registered email succeeds; the reason is recorded10267
AUTH-REG-01LAUTH-REG-01/02 pro_app: fresh email → reason register → owner account with Pro license1144
AUTH-REG-01, AUTH-REG-02LAUTH-REG-02 portal: registration succeeds under the portal flavor330
AUTH-REG-03LAUTH-REG-03 a wrong OTP → 401, and the email stays registrable566
AUTH-REG-04LAUTH-REG-04 register-OTP request for a registered email → 400159
AUTH-REG-08LAUTH-REG-08 registering with a non-Pro licenseBaseID: outcome recorded153
AUTH-REG-07LAUTH-REG-07 resend answers 200 and the code still registers361
AUTH-DEL-01LAUTH-DEL-01 the authenticated delete-OTP request answers the userDelete session767
AUTH-DEL-02LAUTH-DEL-02 (needs the fixed-OTP-for-delete convention) delete succeeds; the account is provably gone12454
AUTH-DEL-03LAUTH-DEL-03 a wrong delete code answers 401 yet must NOT delete1060
AUTH-DEL-04LAUTH-DEL-04 requesting a delete OTP without a Bearer token → 401436
AUTH-RED-04LAUTH-RED-04 GET /debug/errors/device-limit → 310 with the documented body shape271
AUTH-RED-04LAUTH-RED-04 GET /debug/errors/user-not-enabled → 311 with the documented body shape255
AUTH-RED-04LAUTH-RED-04 GET /debug/errors/open-invitations → 312 with the documented body shape147
AUTH-RED-04LAUTH-RED-04 GET /debug/errors/abort/314 → 314 with the flavor-mismatch body60
AUTH-RED-01LAUTH-RED-01 fresh device ids until 310; remove a session; login again1132
AUTH-ROLE-02LAUTH-ROLE-02 mint an athlete via createUser; first login explored + RBAC asserted799
AUTH-ROLE-03LAUTH-ROLE-03 mint a coach via createUser; first login explored696
AUTH-DEL-05LAUTH-DEL-05 the owner deletes a minted child; the assumed route's outcome is recorded1056
AUTH-GATE-01LAUTH-GATE-01 login under the portal api-key but a plain x-user-agent: outcome recorded334
AUTH-GATE-02LAUTH-GATE-02 a bare request without the api-key header: outcome recorded41
AUTH-LOG-07LAUTH-LOG-07 (fixture socialCollision) a social-registered account logs in through the normal OTP flow286
AUTH-LOG-08, AUTH-REG-05, AUTH-REG-06LAUTH-LOG-08/AUTH-REG-06 (fixture legacyPro) legacy-known email → plain register reasons (promotion trigger)296
AUTH-LOG-08, AUTH-REG-05, AUTH-LOG-09LAUTH-LOG-09/AUTH-REG-05 (fixture legacyOne) legacy-known email → plain register reasons (portal)0
AUTH-LOG-10LAUTH-LOG-10 (fixture oneTier) login on the Pro app → 314 with the mismatch body112
AUTH-LOG-10, AUTH-LOG-11LAUTH-LOG-11 (fixture oneTier) login on the portal is ALSO blocked with 314111
AUTH-LOG-14LAUTH-LOG-14 (fixture proPlus) logs in as Pro; license name recorded465

Result key: ✅ pass · ❌ fail · ➖ skipped (fixture missing or soft-skip — see Observations)

Observations (verify-live values — fold back into the matrix)

  • AUTH-DEL-01 delete-OTP request status + body {"status":200,"body":{"reason":"userDelete"}}
  • AUTH-DEL-02 login-OTP reason after a verified delete {"reason":"login"}
  • AUTH-DEL-03 raw status+body for a WRONG delete OTP (success answers 401; live 2026-07-27 a wrong code answered 403 — deleteAccount() still proves deletion via the dead-token probe before wiping local data) {"status":403,"body":{"reason":"Wrong or mismatching email address and passcode."}}
  • AUTH-DEL-04 unauthenticated delete-OTP request {"status":401}
  • AUTH-LOG-02 pro_app owner privilegeKeys after login ["showLiveHubSection","writeUserStatus","writeCustomCharts","canWritePlanner","canArchive","canAccessPro","canAccessPortal","readSubUser","modifyUserAdmin","modifyUserTrainer","modifyUserAthlete","modifyUserTag","showTeamDashboardSection","showInsightsSection","showManagementSection","showMultiUserScheduleCalendar","deleteSelf","writeDeviceSession","writeSelf","writeUserAdmin","writeUserTrainer","writeUserAthlete","writeUserTag","writeData","writeExercise","writeBetaTester","writeTrainingGoal","writeEquipmentAndLimitations","readLicense","featureMigration","featureDataExport","featureUserBatchUpload","featureTrackingOnly","featureMultiUserTraining","writeEntityTag"]
  • AUTH-LOG-03 wrong login OTP: status + body {"status":403,"body":{"reason":"Wrong or mismatching email address and passcode."}}
  • AUTH-LOG-04 correct code after 3 wrong attempts (docs say: rejected) {"wrongStatuses":[403,403,400],"status":400}
  • AUTH-LOG-06 login-OTP reason for an unknown email {"reason":"login"}
  • AUTH-REG-02 fresh owner: role, license fields, privilegeKeys {"roleId":"46381D7A-2DA5-4B53-B3B3-D129AA9240D6","roleKey":"owner","licenseBaseID":null,"licenseBaseIdNested":"852E8114-0301-4C1E-AF30-86F1A77EF118","licenseName":"Enode Pro","privilegeKeys":["showLiveHubSection","writeUserStatus","writeCustomCharts","canWritePlanner","canArchive","canAccessPro","canAccessPortal","readSubUser","modifyUserAdmin","modifyUserTrainer","modifyUserAthlete","modifyUserTag","showTeamDashboardSection","showInsightsSection","showManagementSection","showMultiUserScheduleCalendar","deleteSelf","writeDeviceSession","writeSelf","writeUserAdmin","writeUserTrainer","writeUserAthlete","writeUserTag","writeData","writeExercise","writeBetaTester","writeTrainingGoal","writeEquipmentAndLimitations","readLicense","featureMigration","featureDataExport","featureUserBatchUpload","featureTrackingOnly","featureMultiUserTraining","writeEntityTag"]}
  • AUTH-REG-03 wrong register OTP status {"status":403}
  • AUTH-REG-04 register-OTP 400 for a registered email {"status":400}
  • AUTH-REG-08 register with an unknown licenseBaseID was rejected {"status":314,"error":"ApiError: Request failed: 314"}
  • AUTH-ROLE-02 created Athlete's first login {"otpReason":"login","loginStatus":201}
  • AUTH-RED-03 312 fired on the first authenticated request (not on login) {"body":{"userId":"04A9F67A-776F-4361-85FE-B64DE11BB939","reason":"Open invitations","invitations":[{"parentId":"B7857DD8-4C98-4A00-BFAB-88DF14C3465A","accepted":false,"parentUserEmail":"authlive-ms4db7o4-ee22-7c04-1@authtest.enode.ai","parentUserName":"Authlive Roles Org"}]}}
  • AUTH-RED-03 invitation acceptance + resumed request {"acceptStatus":500,"acceptBody":{"reason":"RouteNotFound.404: Not Found"},"resumedStatus":312}
  • AUTH-ROLE-03 created Coach's first login {"otpReason":"login","loginStatus":201}
  • AUTH-RED-03 312 fired on the first authenticated request (not on login) {"body":{"invitations":[{"parentUserEmail":"authlive-ms4db7o4-ee22-7c04-1@authtest.enode.ai","accepted":false,"parentId":"B7857DD8-4C98-4A00-BFAB-88DF14C3465A","parentUserName":"Authlive Roles Org"}],"reason":"Open invitations","userId":"5D459538-1992-4275-83A3-83CB38522A27"}}
  • AUTH-RED-03 invitation acceptance + resumed request {"acceptStatus":500,"acceptBody":{"reason":"RouteNotFound.404: Not Found"},"resumedStatus":312}
  • AUTH-DEL-05 DELETE /users/{id} with the owner's token (route marked TODO in api/users.ts) {"status":204}
  • AUTH-DEL-05 owner org listing after delete {"listingStatus":200,"stillListed":false}
  • AUTH-RED-04 debug device-limit: status + body keys {"status":310,"bodyKeys":["sessions","sessionRemoveToken","reason"]}
  • AUTH-RED-04 debug user-not-enabled: status + body keys {"status":311,"bodyKeys":["reason","userDto"]}
  • AUTH-RED-04 debug open-invitations: status + body keys {"status":312,"bodyKeys":["reason","userId","invitations"]}
  • AUTH-RED-04 debug abort/314 body {"reason":"[DEBUG] abort 314 "}
  • AUTH-RED-01 device limit did NOT fire within 8 fresh-device logins — either the licence's limit is higher (raise ENODE_TEST_DEVICE_LIMIT_TRIES) or phone-type sessions do not count as expected {"attempts":8}
  • AUTH-GATE-01 portal api-key WITHOUT 'enodeportalwebapp' in x-user-agent (the backend gate does a case-sensitive contains() on it) {"otpStatus":200,"loginStatus":201}
  • AUTH-GATE-02 OTP request without any api-key header {"status":400,"body":"{\"reason\":\"Missing api-key field in header\"}"}
  • AUTH-LOG-07 login-OTP request for a social-registered account {"status":200,"body":{"reason":"login"}}
  • AUTH-LOG-07 OTP login for a social-registered account {"status":201}
  • AUTH-LOG-08 legacyPro OTP-request reasons {"loginStatus":200,"loginReason":"register","registerStatus":200,"registerReason":"register"}
  • AUTH-LOG-10 One user on pro_app: login status + body {"status":314,"body":{"appFlavor":"pro_app","currentTier":"Enode One","missingPrivileges":["canAccessPro"],"reason":"App flavor mismatch"}}
  • AUTH-LOG-11 One user on portal: login status + body {"status":314,"body":{"appFlavor":"portal","missingPrivileges":["canAccessPortal"],"reason":"App flavor mismatch","currentTier":"Enode One"}}
  • AUTH-LOG-14 proPlus account: tier facts. Live 2026-07-28: the Pro+ license ('Enode Pro+') has its OWN license base — isProLicenseBaseID() (the single-id stopgap) returns FALSE for it, so id-based Pro checks misclassify Pro+ accounts; the truthful tier signal is the canAccessPro privilege. {"licenseBaseID":"7853FCB4-F1C2-4D4F-A822-E51F34A2B9EB","isProByBaseId":false,"licenseName":"Enode Pro+","privilegeKeys":["showLiveHubSection","writeUserStatus","writeCustomCharts","canWritePlanner","canArchive","canAccessPro","canAccessPortal","readSubUser","deleteSelf","writeDeviceSession","writeSelf","writeUserAdmin","writeUserTrainer","writeUserAthlete","writeUserTag","writeData","writeExercise","writeBetaTester","writeTrainingGoal","writeEquipmentAndLimitations","readLicense","featureMigration","featureDataExport","featureUserBatchUpload","featureTrackingOnly","featureMultiUserTraining","writeEntityTag","writeCloudStorage"]}

Disposable-user leftovers

1 account(s) were not verifiably deleted during the run. Run npm run test:live:auth:sweep — it re-logs each one in under a fresh device identity and self-deletes it; whatever it cannot remove is listed for manual follow-up:

  • authlive-ms4db7o4-ee22-edc1-4@authtest.enode.ai

Coverage vs the case matrix

CaseStatus this run
AUTH-LOG-12unit layer (U) — include with --with-unit
AUTH-LOG-13NOT executed — fixture missing or not yet implemented
AUTH-LOG-15unit layer (U) — include with --with-unit
AUTH-REG-09aNOT executed — fixture missing or not yet implemented
AUTH-REG-09bunit layer (U) — include with --with-unit
AUTH-REG-09cNOT executed — fixture missing or not yet implemented
AUTH-REG-09dNOT executed — fixture missing or not yet implemented
AUTH-ROLE-01NOT executed — fixture missing or not yet implemented
AUTH-ROLE-04unit layer (U) — include with --with-unit
AUTH-RED-02NOT executed — fixture missing or not yet implemented
AUTH-RED-03observed via exploration this run (see Observations)
AUTH-RED-05unit layer (U) — include with --with-unit
AUTH-GATE-03NOT executed — fixture missing or not yet implemented
AUTH-ERR-01server-side only (S) — mirrored by the backend suite
AUTH-ERR-02server-side only (S) — mirrored by the backend suite
AUTH-ERR-03browser smoke only (E) — recorded manually

Executed but not fully passing: AUTH-RED-01, AUTH-LOG-09 (see Results/Failures).

Defect log

#Case refSeverity (blocker/major/minor)What happenedExpectedDetail

Sign-off

  • Mandatory cases executed: see Coverage table
  • Open blockers/majors: fill in
  • Verdict: fill in — by name, 2026-07-28

Fully green run (31 pass / 0 fail; skips = the deliberately empty legacyOne fixture and the 310 soft-skip, handoff Q7). Post-run sweep verified all disposable accounts removed except the known 312-orphan (handoff Q1).