Skip to content

Refactor hot-spots (012): foundational dedup + quiz-overlay XSS fix + answer-reveal/instructor-auth consolidation#93

Merged
IanMayo merged 3 commits into
mainfrom
claude/vibrant-galileo-ynb7mj
Jun 19, 2026
Merged

Refactor hot-spots (012): foundational dedup + quiz-overlay XSS fix + answer-reveal/instructor-auth consolidation#93
IanMayo merged 3 commits into
mainfrom
claude/vibrant-galileo-ynb7mj

Conversation

@IanMayo

@IanMayo IanMayo commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the first, independently-shippable slices of feature 012-code-review (/speckit.implement 12) — Phases 1–3 in full and the high-value security/duplication work of Phase 4 (US2). Every slice is behavior-preserving (the one sanctioned exception being the quiz-overlay XSS fix) and gated by the full Definition of Done.

The work follows the spec's own incremental-delivery strategy (SC-006): each commit is green and mergeable on its own.

What's included

Phase 1 — Baseline (T001–T002)

  • Recorded the regression budget in quickstart.md: 782 unit + 67 integration tests; 36.71 KB gzip bundle (limit 40 KB); the 8 files >400 lines.

Phase 2 — Foundational consolidation (T003–T008, no behavior change)

  • INSTRUCTOR_SHOW_ANSWERS_KEY constant replaces the 'qd/instructor/showAnswers' magic string in 5 modules.
  • New utils/page-id.ts getPageIdFromUrl() replaces 3 inline pathname→filename→strip-.html parses (with unit tests).
  • clearBadges(link) helper replaces 3 duplicated badge-stripping loops.
  • createEmptyStudentRecord(session) replaces the two duplicated new-record literals.
  • spinnerStyles extracted into components/shared-styles.ts (adopted by the migration dialog).

Phase 3 — Maintainer report verified (T009–T011)

  • Confirmed code-review-report.md lists every src/** file >400 lines with line count/severity/decomposition, addresses all five hot-spot criteria with file/line refs, and provides a lowest-risk→highest-payoff sequence. Reconciled against the T002 baseline.

Phase 4 — Security & duplication (US2, partial)

  • 🔒 Quiz instructor-overlay XSS fix (FR-004): student-supplied name/answer now rendered via textContent/element construction instead of innerHTML, so injected HTML is inert text. Characterization + XSS-regression integration tests added (T012/T013/T020).
  • Single shared answer-reveal (enhancers/instructor-answer-reveal.ts): both bootstrap.ts (initial-load) and event-coordinator.ts (post-login) now call one function; behavior preserved exactly via an addInstructorClass option. Characterization tests added (T014/T019).
  • Shared instructor-auth (services/auth/instructor-auth.ts): one SHA-256 + 12-char hashing implementation, consumed by both qd-login and qd-migration-dialog; duplicated crypto deleted; instructor-hash config reads routed through it (T016/T017, partial T018).

Verification

Final Definition of Done — all green:

  • typecheck, lint, format:check clean
  • 800 unit + 75 integration tests passing
  • build OK; bundle 36.94 KB gzip (within the 40 KB budget, no regression)

Deferred to follow-up

The remaining tasks are large and security-sensitive; rushing them would risk the behavior regressions the spec's golden rule guards against. They are best delivered as further independent slices:

  • T021 / T015 / remainder of T018AuthService extraction collapsing the ~100-line handleStudentLogin/retryLoginAfterMigration duplicate and routing the remaining dbName/title config reads (these are entangled with custom error semantics, so they belong with the AuthService move).
  • US3 (T022–T043) — decompose the six oversized modules (indexeddb.ts, quiz-table.ts, analysis-table.ts, bootstrap.ts, session.ts, qd-login.ts) below ~400 lines.
  • US4 (T044–T050) — reusable Lit components (note: only ~3 KB of gzip headroom remains).
  • Polish (T051–T056).

🤖 Generated with Claude Code


Generated by Claude Code

claude added 3 commits June 19, 2026 10:47
Wave-1 zero-behavior-change dedup that later slices build on:

- Add INSTRUCTOR_SHOW_ANSWERS_KEY constant; replace the
  'qd/instructor/showAnswers' magic string across quiz-table,
  qd-instructor, session, bootstrap, event-coordinator (T003)
- Add utils/page-id.ts getPageIdFromUrl(); replace the inline
  pathname->filename->strip-.html parses in bootstrap (x2) and
  event-coordinator, with unit tests (T004/T005)
- Add clearBadges(link) helper in home-badges; replace 3 duplicated
  badge-stripping loops (T006)
- Add createEmptyStudentRecord(session) in storage-service; replace
  the two duplicated new-record literals in loadStudentRecord (T007)
- Extract spinnerStyles into components/shared-styles.ts and adopt in
  qd-migration-dialog (T008; divergent error/button styles left intact
  to preserve exact rendering per the behavior-preservation rule)

DoD: typecheck, lint, 791 unit + 67 integration tests, format, build,
size-check (36.95KB gzip) all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tK4JXdkC4s9rYYywjYNiv
Security/duplication fixes (Phase 4, partial):

- Fix innerHTML XSS in the quiz instructor overlay (FR-004): student
  name/answer now rendered via textContent + element construction, so
  any HTML they contain is inert text. Adds characterization +
  XSS-regression integration tests (T012/T013/T020).
- Extract enhancers/instructor-answer-reveal.ts as the single shared,
  security-sensitive answer-reveal path; bootstrap (initial-load, adds
  qd-quiz-instructor class) and event-coordinator (post-login) now both
  call it. Behavior preserved exactly via an addInstructorClass option.
  Adds characterization tests (T014/T019).

Export QuizTableMetadata type for the shared enhancer.

DoD: typecheck, lint, 791 unit + 75 integration tests, format, build,
size-check (36.87KB gzip) all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tK4JXdkC4s9rYYywjYNiv
- Add services/auth/instructor-auth.ts (hashPassword,
  getExpectedInstructorHash, verifyInstructorPassword) as the single
  source of instructor-password hashing (SHA-256 + 12-char truncation),
  with unit tests (T016/T017, FR-008).
- Route qd-login.handleInstructorLogin and
  qd-migration-dialog.validatePassword through it, deleting the
  duplicated crypto. Instructor-hash config reads now go through the
  shared module (partial T018).

DoD: typecheck, lint, 800 unit + 75 integration tests, format, build,
size-check (36.94KB gzip) all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tK4JXdkC4s9rYYywjYNiv
@github-actions

Copy link
Copy Markdown
Contributor

🚀 PR Preview Deployment

✅ Your changes are being built and deployed to a preview environment.

📋 Live PR Preview Links:

ℹ️ About PR Previews:

📦 Production Demo (main branch):

🧪 Testing Locally:

npm install
npm run build
# Open demo/quiz-index.html in your browser (use file:// or http-server)

This comment will be automatically updated when you push new commits.

github-actions Bot added a commit that referenced this pull request Jun 19, 2026
@IanMayo IanMayo merged commit dc2d902 into main Jun 19, 2026
7 checks passed
@IanMayo IanMayo deleted the claude/vibrant-galileo-ynb7mj branch June 19, 2026 11:03
github-actions Bot added a commit that referenced this pull request Jun 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants