Alice Technical Journal – 2026-01-28
What I have done
Homework publish scheduling (published_at)
- Implemented
published_at consistently across:
- Teachers > Homework Create / Edit
- Admin > Academic > Homework Edit
- Admin > Academic > Homework Assign modal
- Enforced customer visibility strictly on the backend:
- Customer queries filter:
published_at IS NULL OR published_at <= now()
- Direct URL access blocked when not yet published
- Standardized semantics:
null = immediate visibility
- future datetime = hidden
- Fixed edge case where clearing
published_at resulted in 0 affected rows, which was incorrectly treated as an error.
- Ensured all update flows send explicit
published_at values (ISO string or null).
Homework cloning (backend-first)
- Removed frontend “Copy” logic where backend clone already exists.
- Implemented Admin Homework clone by reusing Teachers’ clone logic:
- Single transaction
- Clones homework core fields + links/skills
- Does NOT clone submissions, proofs, or completion state
- Ensured Admin clone follows exact Teachers behavior (no semantic drift).
- Verified clone endpoints return new homework IDs for redirect/list refresh.
Teacher Homework Edit stability & UX
- Restored missing student assignment section.
- Implemented class-based filtering and bulk assign/unassign:
- Avoided incorrect
students.class_id assumptions
- Used relationship-derived class mapping instead
- Fixed Radix Select runtime crashes:
- Removed
value="" from <SelectItem>
- Introduced explicit sentinel value (
"__all__")
- Fixed silent save bug:
- Root cause: PUT requests sent empty payloads
- Solution: ensure
useForm state is bound to inputs and passed explicitly to router.put
- Removed all temporary debug logging after verification.
- Adjusted sidebar behavior as page complexity increased, then reverted sticky behavior when it became counterproductive.
Direct upload experiments (and rollback)
- Attempted direct-to-R2 upload:
- Introduced upload init/finalize flow
- Generated presigned PUT URLs
- Hit Flysystem limitation: adapter does not expose
S3Client
- Reimplemented presigning with explicit AWS SDK client
- Encountered R2 browser constraints:
- CORS configuration subtleties (OPTIONS handling, allowed headers)
- Browser masking auth failures as CORS errors
- Attempted Google Drive fallback:
- Integrated Google Drive service account backend
- Verified connection via Artisan command
- Hit Google Picker complexity (OAuth, API enablement, origin restrictions)
- Made a deliberate rollback decision:
- Hard reset to stable commits when upload paths became too risky
- Preserved system integrity over partial success
Infrastructure & safety discipline
- Performed multiple controlled git hard resets to known good commits.
- Reinforced rule: experiments must not pollute mainline stability.
- Ensured queue workers, caches, and config were reset after each rollback.
What I have learned
Backend truth > UI assumptions
- Many “working” UIs were lying:
- Success toasts fired without DB writes
- Update endpoints returning 200 while doing nothing
- Logging request payloads + DB effects is the fastest way to kill these bugs.
SQL semantics matter
UPDATE ... SET column = NULL returning 0 rows is not an error.
- Treating “rows affected” as a success signal is dangerous without context.
Abstractions break at infrastructure boundaries
- Flysystem is fine for storage, but:
- Presigned URLs
- Browser uploads
- Advanced cloud behavior
require native SDK control.
- Assuming adapters expose internals leads to dead ends.
CORS errors are often lies
- Browser CORS errors frequently hide:
- Signature mismatch
- Header mismatch
- Permission errors
- Real debugging requires:
curl with the presigned URL
- Inspecting raw S3/R2 XML error responses
Google Drive has a hard auth split
- Service account = backend automation
- Browser uploads = user OAuth
- Google Picker increases surface area and fragility
- Trying to “simplify” Drive uploads without respecting this split causes instability
Resetting is an engineering skill
- Knowing when to stop and reset prevented Alice from becoming untestable.
- Hard resets are cheaper than weeks of duct-tape fixes.
- Stability is a feature.
Reuse beats speed
- Reusing Teachers flows for Admin (clone, scheduling, assignments) reduced bugs.
- Any divergence between Admin and Teacher behavior is technical debt waiting to explode.