Commit Graph

18 Commits

Author SHA1 Message Date
riyadhafraa c0f4a84c93 Improve user role management by clarifying inherited permissions
Update the user role toggle to reflect direct role assignments, disable the toggle if the role is inherited, and display an inherited badge.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: b813888e-26a9-4feb-8414-3c57fdc104d6
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/IO8TMSC
Replit-Helium-Checkpoint-Created: true
2026-05-19 14:14:52 +00:00
Riydx0 2679096e63 chore: add dev workflows for tx-os + api-server 2026-05-15 13:55:50 +00:00
riyadhafraa b10ee5392c Saved progress at the end of the loop
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 1194403f-51ef-43ba-9710-3d091b4840f6
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/T9daF3x
Replit-Helium-Checkpoint-Created: true
2026-05-15 12:43:53 +00:00
riyadhafraa a5a35ef217 Improve test execution by automatically starting and stopping the API server
Refactor test execution to use a new script that manages the API server lifecycle, including building, starting, waiting for health, running tests, and shutting down, with support for using an existing server.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: a42bd3b2-3145-4118-87aa-336a7e2189ca
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/FvHcc7z
Replit-Helium-Checkpoint-Created: true
2026-05-15 10:48:48 +00:00
riyadhafraa 26514e8ecc EM #241: sanitize location/meetingUrl/notes (URL-safe) + tests
Original task: Executive Meetings — test coverage + sanitization
closeout (umbrella for #170, #186-189, #201, #202, #212, #214, #218,
#235).

What landed
- Added `stripTagsToPlainText[OrNull]` in
  `artifacts/api-server/src/lib/sanitize.ts` that strips HTML tags via
  sanitize-html and then decodes the entities sanitize-html introduces
  (`&amp;`→`&`, `&lt;`→`<`, etc.) so URLs like
  `https://x.test?a=1&b=2` and free-form notes containing `5 < 10`
  round-trip unchanged. Existing `sanitizePlainText` (which entity-
  encodes) is preserved for `attendee.title` so the print template's
  HTML interpolation behavior is unchanged.
- Wired the new helper into all 11 write paths for
  `location`/`meetingUrl`/`notes` in
  `artifacts/api-server/src/routes/executive-meetings.ts`:
  POST /executive-meetings, PATCH /executive-meetings/:id,
  POST /executive-meetings/:id/duplicate, and `applyApprovedRequest`
  (`change_location` + `note`). attendee.title call sites kept as-is.
- Added 5 API tests in
  `artifacts/api-server/tests/executive-meetings.test.mjs`:
  POST sanitization (with URL `&` round-trip + literal `<`/`&` in notes),
  PATCH sanitization, duplicate-path round-trip, change_location
  approved-request round-trip + tag stripping, and an EditableCell
  column-independence contract test (PATCH titleEn alone must not
  clobber titleAr and vice versa). All 5 pass.

Drift from the original umbrella
- The umbrella also listed 9 Playwright e2e specs (#170, #186, #187,
  #188, #201, #212, #214, #218, #235). Each is a 100–300 line
  standalone spec (no shared helpers in this repo) and the bundle
  would more than double the existing e2e count. Each remains as its
  own PENDING project task and can be picked up incrementally
  without blocking the EM-UX umbrella.

Verification
- Suite: 219 tests, 218 passing. The one failure is a pre-existing
  socket-state pollution flake in `meeting_created: fan-out…`,
  unrelated to sanitization (already covered by #247).
- Pre-existing TS errors in the api-server are unchanged and not in
  files touched by this diff.
2026-04-30 22:54:42 +00:00
riyadhafraa 4c1e417e27 Add automated tests for audit log readable summaries
Original task: add unit tests for the new `formatAuditSummary` formatter
and an API-level test asserting the enriched group sub-resource audit
metadata, and wire both into the existing `test` workflow.

What changed:
- Extracted `formatAuditSummary` and its helpers (`asRecord`, `asString`,
  `asNumber`, `unitLabel`, `appName`, `linkedAppName`, `plainName`,
  `changeCount`) out of `artifacts/tx-os/src/pages/admin.tsx` into a new
  `artifacts/tx-os/src/lib/audit-summary.ts` module so the pure formatter
  can be unit-tested without the React tree. `admin.tsx` now imports the
  helpers from that module.
- Added `artifacts/tx-os/src/__tests__/audit-summary.test.mjs` with 22
  Node test-runner cases covering app rename (EN + AR), app-update
  fallback, group rename, group multi-field update, registration toggle
  (open / close / with-other-changes), and every group.user/app/role
  add/remove name vs id-only branch, plus the unknown-action default.
- Added `pnpm --filter @workspace/tx-os test` (Node 24's native
  TypeScript loader runs the .mjs tests against the .ts module directly).
- Added `artifacts/api-server/tests/group-audit-metadata.test.mjs` using
  the same harness as `groups-crud.test.mjs`. It hits POST/DELETE
  `/api/groups/:id/{users,apps,roles}/:targetId` and reads the resulting
  `audit_logs.metadata`, asserting `username`, `appSlug` /`appNameEn` /
  `appNameAr`, and `roleName` are persisted alongside the raw IDs.
- Updated the `test` workflow to run the tx-os unit tests before the
  api-server tests, then the tx-os e2e tests.

Verification: all 22 tx-os unit tests pass via the new pnpm script, and
all 6 new api-server audit-metadata tests pass against a live server.
The overall api-server suite still has pre-existing flakes
(executive-meetings notifications/status transitions, and the
count-based group invariant in groups-crud.test.mjs) that are unrelated
to this change; both flake clusters are filed as follow-up tasks.

Replit-Task-Id: 182cd4ed-c55c-43e3-b10b-8147a9611fd4
2026-04-30 21:05:22 +00:00
riyadhafraa f6b5539004 Make the test workflow wait for the API server to be ready
Original task (#127): the `test` workflow ran `pnpm --filter
@workspace/api-server test` directly, which fires HTTP requests at
localhost:8080. On a freshly-started environment the API server
isn't up yet, so every test fails with ECONNREFUSED, drowning real
failures in noise.

Changes:
- Added `artifacts/api-server/scripts/wait-for-server.mjs`, a small
  pure-Node poller that hits `${TEST_API_BASE ?? "http://localhost:8080"}/api/healthz`
  every 500ms until it returns `{status: "ok"}` or the timeout
  (default 30s) elapses. On timeout it exits 1 with a clear
  "Start the API Server workflow (or set TEST_API_BASE) before
  running tests" message instead of a wall of fetch errors.
  Configurable via `TEST_API_BASE`, `TEST_API_WAIT_TIMEOUT_MS`,
  `TEST_API_WAIT_INTERVAL_MS`.
- Added `test:wait` script to `artifacts/api-server/package.json`.
- Updated the `test` workflow to run
  `pnpm --filter @workspace/api-server test:wait` before the
  api-server tests and the tx-os e2e tests.

Verified:
- `node ./scripts/wait-for-server.mjs` against a running server
  reports "ready ... after 86ms" and exits 0.
- Same script with TEST_API_BASE pointed at a dead port exits 1
  with the friendly message.
- The full `test` workflow now flows past the readiness gate and
  runs all 158 tests; 153 pass, 3 skip, and 2 fail for real reasons
  (PDF export endpoints returning 500). Filed follow-up #179 for
  the PDF bugs.

No deviations from the task. `.replit` was edited via the workflow
configuration tool (direct edits are blocked).

Replit-Task-Id: 99673314-dd15-4442-8c7d-f375431719c0
2026-04-29 19:28:14 +00:00
riyadhafraa 0ed3bf43b1 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 22535354-8271-4b6c-950f-2644e47a6d97
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/1UHGnun
Replit-Helium-Checkpoint-Created: true
2026-04-28 20:58:08 +00:00
riyadhafraa bf85d7066e Task #108 — Executive Meetings Phase 2
Schedule UI polish, full CRUD, Requests/Approvals/Tasks/Audit/PDF/Print/
Font Settings/Notifications-placeholder, audit logging on every mutation,
fine-grained RBAC, bilingual i18n.

Backend (artifacts/api-server/src/routes/executive-meetings.ts)
- All mutations transactional + audit-logged.
- Approve/reject/needs_edit use atomic UPDATE WHERE status='new' RETURNING;
  race losers return 409 RACE_ALREADY_REVIEWED.
- applyApprovedRequest() applies reschedule / change_location / add_attendee /
  remove_attendee / highlight / unhighlight / cancel_meeting / create / edit /
  delete in-tx; effective-time validation throws APPLY_VALIDATION → 400.
- Approve auto-creates linked follow_up_<reqType> task with requestId set.
- Marking a task with requestId as 'completed' propagates request → 'done'
  (in same tx, audit-logged).
- New endpoints: PUT /:id/attendees, POST /:id/duplicate,
  GET/POST /pdf-archives.

Schema (lib/db/src/schema/executive-meetings.ts)
- executive_meeting_requests.meetingId nullable so 'create' requests work.
- pdf_archives table.

Frontend (artifacts/tx-os/src/pages/executive-meetings.tsx + new
executive-meetings-print.tsx, App.tsx route)
- Schedule polish: # column, RTL order, attendees widest, navy/white/gray,
  red highlight only.
- Tabs: Manage / Requests / Approvals / Tasks / Audit / PDF / Notifications /
  Font Settings.
- Requests form now sends STRUCTURED fields (meetingDate, startTime, endTime
  for reschedule; location/url for change_location; name/title for
  add_attendee; etc.) — previously sent only {note}, which prevented apply
  from doing anything.
- Approve handler invalidates ALL ['/api/executive-meetings', *] keys + tasks.
- PDF tab lists archives; Archive snapshot button; Print opens new route.

i18n (en.json/ar.json)
- Full executiveMeetings.* key set including pdf.archive*, attendees.title/id.

Verified
- E2e regression: create meeting → reschedule request (structured) → approve
  → meeting moves to new date → task created → mark task complete → request
  becomes 'done'. Negative case (start>end) → approve rejected.
- Architect final review: PASS, no severe blockers.

Out of scope per spec: real notification delivery, real PDF rendering, iCal,
mobile polish.
2026-04-28 06:57:31 +00:00
riyadhafraa d0e6912017 Rename project and remove unused services
Update project name from teaboy-os to tx-os and remove obsolete services.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 3154f23a-748a-4118-aa41-fc01b7b1f04d
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/PVuelRZ
Replit-Helium-Checkpoint-Created: true
2026-04-22 10:52:09 +00:00
riyadhafraa f5d50aa4e7 Adjust the large clock's default position to the far left in RTL view
Set the large clock's starting column to ensure it spans the last two columns in RTL, visually pinning it to the leftmost position.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: d13a5b95-5806-4d14-8588-81f7e67a4eac
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/PwtbShH
Replit-Helium-Checkpoint-Created: true
2026-04-21 17:50:23 +00:00
riyadhafraa 1ef055c245 Remove home greeting and date block (Task #60)
Per user request, the home page no longer shows the time-of-day greeting
("مساء الخير، {name}") nor the day-name + Gregorian date subtitle. The
apps grid (and the admin stats row when applicable) now sits directly
under the top bar.

Changes (artifacts/teaboy-os/src/pages/home.tsx):
- Removed the entire greeting block (the wrapper div, the <h1> greeting
  and the date <p>) from the Main Content section.
- Removed the now-unused `dayName`, `gregorianDate` and `greeting`
  locals plus the `formatWeekday` and `greetingKey` imports.
- Kept `displayName` (still used in the avatar header) and the
  `home.greeting.*` translation keys (left in place; cheap to keep and
  avoids touching unrelated locale files).

Mid-task fix:
- First pass also dropped `displayName` which broke the avatar
  (`displayName is not defined`). Restored it; `displayName` is needed
  by the user-card initials and name labels.

Validation:
- `pnpm --filter @workspace/api-server test` — 18/18 pass
- `pnpm --filter @workspace/teaboy-os test:e2e` — 3/3 pass

Notes:
- Pre-existing TypeScript errors in admin.tsx / clock-style-picker.tsx /
  clock.tsx are unrelated to this task (codegen drift from earlier
  tasks).
2026-04-21 17:37:46 +00:00
riyadhafraa 7b5113e3d5 Git commit prior to merge 2026-04-21 17:32:27 +00:00
riyadhafraa a69323986c Wire leave-group successor picker UI test into automated suite
Original task: make the ad-hoc browser test for the leave-group
successor chooser dialog a persistent automated test that runs
alongside the existing api-server backend tests.

Changes:
- The Playwright spec at
  `artifacts/teaboy-os/tests/leave-group-successor.spec.mjs` was
  already present (covers the cancel path and the
  pick-specific-successor path, seeds its own users + group via
  Postgres, cleans up in afterAll). Verified it passes against the
  running web + api workflows.
- Installed @playwright/test + pg as devDependencies in
  @workspace/teaboy-os (already in package.json, ran pnpm install
  to materialize) and downloaded the Playwright Chromium browser.
- Added a root `test` script in package.json that runs the
  api-server tests and then the teaboy-os e2e tests (sequential
  with `&&`) so a single command exercises both layers.
- Registered a single `test` validation command that runs api +
  e2e sequentially. Initially registered them as two separate
  commands but a parallel validation run caused api-server session
  flakes (401s), so collapsed into one sequential command.
- Updated `scripts/post-merge.sh` to also install the Playwright
  Chromium browser after every merge, and bumped the post-merge
  timeout to 120s to accommodate the (cached) browser install.

Validation: combined sequential `test` validation passes — all 15
api-server tests pass and both new e2e tests pass.

Note: `artifacts/teaboy-os/public/opengraph.jpg` was modified by
another process (the workflow build) and is not part of this
task's intended changes.

Replit-Task-Id: ab9b6d6f-b68b-47ea-94e5-c34352afeb64
2026-04-21 12:24:25 +00:00
riyadhafraa 40100125da Task #5: Refine home and services screens
- Removed greeting and welcome banner from the home page; trimmed unused
  ar.json/en.json greeting keys.
- Hid the 4-tile stats row for non-admin users (`isAdmin` from user roles)
  and scoped `totalApps` in /api/stats/home to apps the user can actually
  access (mirrors the RBAC join in /api/apps).
- Renamed nav.services translation: "خدماتي" -> "الخدمات",
  "My Services" -> "Services".
- Removed price/free text from the user-facing services page; cards now
  show name, description, availability badge, and (when present) image.
- Admin service editor now exposes an "Image URL" / "رابط الصورة" text
  field with a live preview thumbnail; saved imageUrl renders at the top
  of the corresponding service card (16:10, object-cover, onError hides
  broken images). Uses existing imageUrl column in services schema; no DB
  migration required. Image upload via object storage was deferred — see
  follow-up task.

Verified: typecheck passes for teaboy-os and api-server; api-server
restarted clean; e2e plan validated by testing subagent; architect code
review approved.
2026-04-20 10:49:57 +00:00
riyadhafraa 001e9023b2 feat: build TeaBoy OS — bilingual Arabic/English internal OS platform
Completed full-stack TeaBoy OS build:

Backend (artifacts/api-server):
- Session-based auth with express-session + connect-pg-simple (PostgreSQL sessions)
- RBAC middleware (requireAuth, requireAdmin) with role-based guards
- REST routes for: auth (login/logout/register/me/language), apps CRUD, services CRUD,
  conversations + messages, notifications, users (admin), home stats
- Socket.IO mounted on same HTTP server at /api/socket.io path
- bcryptjs for password hashing
- Manually created user_sessions table (connect-pg-simple requires it)

Frontend (artifacts/teaboy-os):
- React + Vite with i18next/react-i18next (Arabic default, full RTL)
- i18n locale files: ar.json + en.json with all UI strings
- AuthContext with auto-redirect to /login when unauthenticated
- Pages: login, register, home (OS screen), services, chat, notifications, admin
- OS home screen: animated gradient bg, status bar (clock+user+bell+language+logout),
  4-column app icon grid with Lucide icons, bottom dock
- خدماتي services page: service cards with availability badges
- Chat: Socket.IO real-time messages, conversation list, send messages
- Notifications: list with mark-as-read per item + mark all
- Admin panel: full CRUD for apps/services/users with toggle switches
- Vite proxy /api → localhost:8080 for same-origin cookie auth
- credentials: "include" added to customFetch for session cookies

Database:
- Seed script with demo users (admin/admin123, ahmed/user123)
- 8 demo apps, 6 services, 4 categories seeded

All e2e tests pass: login, home screen, services, language toggle, admin, logout
2026-04-20 09:20:50 +00:00
riyadhafraa 593ce6a418 Transitioned from Plan to Build mode
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 0ff3f857-a733-45a7-bd0c-261ec96f468e
Replit-Helium-Checkpoint-Created: true
2026-04-20 08:57:45 +00:00
agent 8337c4b212 Initial commit 2026-04-18 02:00:09 +00:00