Attendance Delivery Decision
Two Approaches to Replacing the Roster System
June 2026  ·  Pharos Resources  ·  Both options running locally
The Java/GWT Roster application is end-of-life. Two replacement approaches were built during this AI-assisted development exploration: a standalone Laravel app (Present) that runs in its own container, and an attendance module integrated directly into Pharos360 using the same raw PHP patterns the existing codebase uses. Both connect to live Pharos360 data. Both are running right now. This page compares them.
Option A
Present
Standalone Laravel app · runs at present.sandboxdemo.pharos360.com
  • ✓ Complete and working today — all core features built
  • ✓ Modern MVC architecture (Laravel 11, Blade templates)
  • ✓ Single sign-on via shared Pharos360 session
  • ✓ Clean separation — can be updated independently of Pharos360
  • ✓ Deploys as its own container on the existing per-client infrastructure — the same container model the team already runs, so no new server type or hosting model
  • ✗ Two parallel deployments — Pharos360 updates and Present updates are separate tracks
Feature complete
Open Present
Option B
Integrated into Pharos360
Built into the existing app · runs at p360.sandboxdemo.pharos360.com
  • ✓ Single deployment — ships as part of Pharos360, with no separate application to deploy or update
  • ✓ Shared auth, session, and database — no bridging required
  • ✓ Per-client feature flag — pharos.maintenance enables it through Settings
  • ✓ All features working: Take Attendance, Learn Names, History, Export, Event Types, email notifications
  • ✓ Clean feature branch off production, with a test suite (33 checks) and green CI
  • ✓ Security and code-review passes complete, findings fixed
  • ! Still needs the primary developer's review of ~300 shared-code lines before production
Feature complete · needs developer review
Open Pharos360
Side-by-Side Comparison
Factor Option A — Present Option B — Integrated
Infrastructure per client Another container on existing infra None — part of Pharos360
Time to enable for a client Deploy a container and configure Toggle a setting in pharos.maintenance
Feature completeness today Complete Complete (email notifications now built)
Production readiness Test suite + security review done Test suite + reviews done; needs developer sign-off
Ongoing maintenance Two separate systems One system
Rollout control All-or-nothing per deployment Per-client toggle, can be disabled live
Risk if something breaks Isolated from Pharos360 Inside Pharos360 — broader blast radius
Technical Detail

Option A — What was built

Present is a complete Laravel 11 application. Authentication piggybacks on Pharos360's PHPSESSID cookie — if a user is logged into Pharos360, Present reads their session and logs them in automatically. Courses, students, and photos come from the shared PostgreSQL database. Attendance data is stored in the roster_* tables.

The Laravel app has controllers, Blade views, Eloquent models, and middleware — standard Laravel MVC. It is clean, readable, and well-structured. Each client deployment runs as its own container — the same per-client container model already in use — alongside Pharos360.

Option B — What was built

The integrated module adds seven new PHP pages to Pharos360's site/ directory, five helper functions to classes/queries.php, and small edits to three existing files (partials/userland.php, settings.php, login.php). No new tables — it uses the same roster_* tables Present uses. It ships as part of Pharos360, so there is no separate deployment process.

The feature flag: has_attendance is a boolean in site_configuration_settings. When false, all attendance pages redirect to home and the nav link is hidden. Pharos360 looks and behaves exactly as it did before. When pharos.maintenance enables it through Settings, faculty immediately see the Attendance link in the top nav.

What Option B needed — and what's since been done

Auth and session — both options

Faculty access attendance the same way in both options: they log into Pharos360 and click Attendance in the top navigation. Option A takes them to the standalone Present app (via roster.php redirect). Option B takes them to attendance_courses.php inside Pharos360. The nav entry point is identical; the destination differs.

In a client deployment, only one option would be active at a time: roster_url set → Option A; has_attendance enabled → Option B.

Database

Both options use the same roster_* tables in the shared PostgreSQL database. If a client were to switch from Option A to Option B (or vice versa), no data migration would be needed.

What Neither Option Has Yet

Both approaches were built against fake data in a local Docker environment. Since June, both have been substantially hardened — each now has an automated test suite and green CI, and both have had security and code-review passes with the findings fixed. What each still needs before production:

Option B still carries a higher modification risk than Option A — it adds code inside a live production PHP application. A bug in a new page is isolated; a bug in a shared helper in queries.php is not. That's why the remaining gate for Option B is specifically the primary developer's review of the shared-file edits, even with tests and review passes done.
Assessment

If the decision is purely operational

Option B is operationally lighter — one deployment to maintain and a per-client toggle rather than a separate app running alongside Pharos360. The missing email notifications are a few hours of work. The developer review is the same work that would be required for any new Pharos360 feature.

If the decision is about code quality and architecture

Option A is cleaner. Laravel enforces separation of concerns, the codebase is testable by design, and bugs stay isolated from Pharos360. Since the team already works in Laravel and already runs per-client containers, neither the framework nor the extra deployment is a barrier — making it the more defensible long-term choice where code quality is the priority.

What AI-assisted development revealed

Option B was built — seven pages, five helper functions, the feature flag, the nav wiring, and the database write — in a single afternoon session. The Pharos360 PHP patterns are simple enough that an AI can produce working code quickly. Option A took longer to rewrite (it replaced a full Java application) but ended up more structured.

The comparison is not "which one is better code" but "what trade-off fits the team and the clients." Both are real, running, and usable today.

The practical path forward: both options now carry a test suite, CI, and completed review passes, so the decision is less about remaining build work and more about cost of ownership. Option B's remaining input is the one thing that can't be delegated — the primary developer's review of the shared-file edits that run inside the live app — after which it ships as a single per-client toggle with no extra infrastructure. Option A is the stronger choice where isolation and code quality matter most, and because the team already uses Laravel and container-per-client deployments, adopting it adds no new skill or infrastructure burden.
Try Both Right Now

Both options are running in Docker on this machine. Use the flows below to see each one.

Option A

Present — Standalone App

  1. 1 Log into Pharos360 as pharos.maintenance / Maintenance! → Settings → disable Attendance
  2. 2 Use Test User Accounts to become judy.fakey
  3. 3 Click Attendance in the top nav bar
  4. 4 Select a course → Take Attendance → click student cards to mark status
Option B

Integrated — Pharos360 Attendance

  1. 1 Log into Pharos360 as pharos.maintenance / Maintenance! → Settings → enable Attendance
  2. 2 Use Test User Accounts to become judy.fakey
  3. 3 Click Attendance in the top nav bar
  4. 4 Select a course → same workflow as Present, inside Pharos360
  5. 5 Bonus: try the AI Assistant in Manage Attendance

The feature flag can be toggled off at any time to restore the original Pharos360 experience.