diff --git a/workspace/_assets_/nav-data.js b/workspace/_assets_/nav-data.js index 1aa5302..0695fa8 100644 --- a/workspace/_assets_/nav-data.js +++ b/workspace/_assets_/nav-data.js @@ -38,6 +38,7 @@ var NAV_DATA = { title: 'History', path: 'history/index.html', children: [ + { title: 'Sunday, 13 July 2026', path: 'history/2026/07-July/13-Sunday/index.html' }, { title: 'Sunday, 12 July 2026', path: 'history/2026/07-July/12-Sunday/index.html' }, { title: 'Saturday, 11 July 2026', path: 'history/2026/07-July/11-Saturday/index.html' }, { title: 'Friday, 10 July 2026', path: 'history/2026/07-July/10-Friday/index.html' }, diff --git a/workspace/history/2026/07-July/13-Sunday/index.html b/workspace/history/2026/07-July/13-Sunday/index.html new file mode 100644 index 0000000..0495396 --- /dev/null +++ b/workspace/history/2026/07-July/13-Sunday/index.html @@ -0,0 +1,177 @@ + + +
+ + +Sunday, 13 July 2026
+
+ Full centralized auth service created from scratch, deployed to
+ account.rokojori.com, and documented.
+
+ A complete auth service at c:\rokojori\projects\web-projects\rokojori-auth,
+ same stack as Roject (Node.js, Express, ts-node, JSON file storage). Built entirely
+ from scratch this session. Deployed to account.rokojori.com via nginx +
+ systemd + Let's Encrypt on Server A, port 3001.
+
+ Register, login, logout, refresh (body), refresh-session (cookie + redirect),
+ forgot-password, reset-password, GET /me, PATCH /me/settings, POST /me/password,
+ DELETE /me. Access token is a 1-hour HS256 JWT containing userId, email, roles,
+ products, settings. Refresh token is a 30-day UUID stored server-side.
+ Both are set as HttpOnly cookies on .rokojori.com
+ and also returned in the response body for non-browser clients.
+
+ Three built-in roles. superadmin is bootstrapped via
+ INITIAL_SUPERADMIN_EMAIL in .env — fires once on
+ first registration if no superadmin exists. Superadmin can grant/revoke admin
+ on other users; cannot change their own roles. Admin and superadmin get an
+ enhanced profile page with a full user list. Role management controls are
+ superadmin-only.
+
+ In-memory per-IP rate limiters on all sensitive endpoints. Login: 10 attempts /
+ 15 min, 3 s delay after attempt 5. Register: 5 / hour. Forgot-password: 20 / 20 min
+ with escalating delay (5 s → 15 s → 30 s). trust proxy enabled so
+ real client IPs are seen behind nginx.
+
+ Five self-contained pages: login, register, profile, forgot-password, reset-password.
+ Plain HTML with inline CSS and JS. Login and register accept a ?redirect=
+ query param. Reset-password fetches the email for the token via
+ GET /api/auth/reset-token-email and populates a hidden email field
+ so browsers offer to update the saved password. Profile page includes
+ change-password (with current password verification) and a two-step delete account
+ confirmation. Welcome email sent on registration (non-blocking).
+
+ GET /api/admin/users (admin + superadmin) lists all users without
+ password hashes. PATCH /api/admin/users/:id/roles (superadmin only)
+ sets roles on another user. Guards: cannot change own roles; user
+ base role is always preserved.
+
+ Created workspace/ in the rokojori-auth repo with the same asset
+ system as the Roject workspace (styles, nav, breadcrumb). A single
+ workspace/index.html covers features, technical implementation,
+ data model, JWT payload, deployment, planned work, and a reference to the
+ Roject workspace for guides and actions.
+
+ Originally the refresh token was only returned in the response body. Added a
+ refresh token cookie so browser clients can silently refresh via
+ GET /api/auth/refresh-session?redirect=... without re-login.
+ Non-browser clients continue to use the body token and
+ POST /api/auth/refresh.
+
+ The PATCH /api/admin/users/:id/roles endpoint blocks changes to the calling + user's own record to prevent accidental self-demotion or lockout. +
++ SMTP failures on the welcome email are caught and silently ignored so that a + misconfigured mail server cannot break user registration. +
+
+ The response is always { ok: true } regardless of whether the email
+ exists, preventing account enumeration via timing or response differences.
+
+ Integrate Roject with rokojori-auth: remove the local user system from Roject,
+ add JWT verification middleware, redirect login/logout to
+ account.rokojori.com, and update all data references from local
+ user records to userId from the JWT payload.
+
rokojori-auth built and deployed — standalone auth service at account.rokojori.com with JWT tokens, refresh cookies, roles, rate limiting, admin panel, and workspace documentation.
+Full directory restructure and first production deployment — source/, build/, source/pages/; Roject live at roject.rokojori.com via nginx + systemd. EmailService SMTP layer added.
diff --git a/workspace/outline/index.html b/workspace/outline/index.html index 0030651..ba04077 100644 --- a/workspace/outline/index.html +++ b/workspace/outline/index.html @@ -231,17 +231,17 @@
- The user system currently embedded in Roject is being extracted into a
- standalone auth service, rokojori-auth, deployed at
- account.rokojori.com. It will handle registration, login,
- JWT issuance, password reset, and user data (roles, products, settings)
- for all rokojori projects. Roject will become a JWT-validating client
- with no user storage of its own.
+ The standalone auth service rokojori-auth is built and live at
+ account.rokojori.com. It handles registration, login, JWT issuance,
+ refresh token rotation, password reset, roles (user / admin / superadmin),
+ products, global settings, rate limiting, and account deletion.
+ Roject has not yet been integrated — that is the next step.
- See auth-restructure for the full plan. + See auth-restructure for the full plan and + the rokojori-auth workspace for implementation details.
+ Roject needs to be updated to become a JWT-validating client. The work involves
+ removing the existing session-based user system and replacing it with JWT
+ verification middleware that reads the shared .rokojori.com cookie.
+ Login and register links will point to account.rokojori.com.
+ Expired tokens are refreshed via
+ account.rokojori.com/api/auth/refresh-session?redirect=....
+ All data models that currently reference a local user record will switch to
+ referencing userId from the JWT payload.
+
source/server/routes/auth.ts and middleware/auth.tssource/server/db.tsbcryptjs, express-sessionsource/pages/login.html, register.htmlsource/server/email/ (already lives in rokojori-auth)account.rokojori.com