Specifikation: Förbättrad integration Google Classroom (synkgrund, v1)

Variant

Vklass V2 (vklassv2). Starters: documentation/templates/vklassv2/{role}-starter.html.

Roller

  • Lärare (teacher.html) — Kerstin Berg: kursens Classroom-yta för Svenska 7A: koppling, pre-flight, synkstatus, deltagardiff, manuell synk, uppgifter (CourseWork), jobblogg
  • Org-/IT-admin (admin.html) — Anders Bergman: synkprofil, paus/feature flag, statusöversikt med filter, riktade jobb, legacy-backfill (kontrolläge), auditlogg
  • Skolledare/rektor (rektor.html) — Magnus Widén: aggregerad integrationshälsa för Proximaskolan
  • Elev (student.html) — Anna Andersson: uppgifter med konsekvent status, "Öppna i Classroom", återkoppling
  • Vårdnadshavare (custodian.html) — Eva Andersson: barnets planering/uppgifter/status utan Google-konto

Användningsfall (UC)

UC-1: Se kursens Classroom-status (lärare)

  • Aktör: Lärare
  • Förutsättning: Kursen Svenska 7A är kopplad till ett Classroom; synk är aktiv.
  • Flöde:
    1. Läraren öppnar kursens Classroom-yta.
    2. Vklass visar koppling (ny mappning + legacy-koppling), synkprofil, status (Aktiv), senaste lyckade körning, nästa planerade körning, förväntad latens och tillåtna åtgärder.
  • Resultat: Läraren förstår integrationens läge utan support.
  • Acceptanskriterier:
    • Status visas med text + etikett (badge), inte enbart färg (R-01, R-02).
    • Kopplingsdetaljen visar GoogleClassroomCourseMapping (Classroom-id, status, version, senaste synk) och bevarad legacy-koppling (R-23).
    • Synkprofil (objektkategorier, riktning, masterfält, schema) visas läsbart.
    • Degraderat läge demonstreras: en kurs i tillståndet "Fördröjd" (kvot/rate limit) med kort arbetsflödesnära text (R-24).

UC-2: Koppla kurs till Classroom med pre-flight (lärare)

  • Aktör: Lärare
  • Förutsättning: En kurs (Engelska 7B) är ännu inte kopplad.
  • Flöde:
    1. Läraren väljer "Koppla till Google Classroom".
    2. Dialog: Skapa nytt Classroom eller Länka befintligt (val av befintlig Classroom-kurs).
    3. Vklass kör pre-flight; resultat visas som OK/Varning/Blockerare med felkod, felklass, kundvänlig text, rekommenderad åtgärd, kontrolltid, giltighetstid och expanderbar teknisk detalj.
    4. Varning kräver explicit bekräftelse; blockerare inaktiverar aktivering.
    5. Vid godkänt: mappning skapas, synk aktiveras, kvittens visas.
  • Resultat: Kursen är kopplad med beständig mappning; legacy-kopplingen bevaras.
  • Acceptanskriterier:
    • Båda vägvalen finns (R-03).
    • Pre-flight-resultat i tre klasser; blockerare stoppar; varning kan inte tyst ignoreras (R-04, R-05).
    • Pre-flight skiljer minst: konfiguration saknas, Classroom ej aktiverat, scope/delegering saknas, Google-konto saknas, konto ej mappat, fel domän, policy/tjänst blockerar, kurs/deltagare kan inte hanteras (§ 5.2).

UC-3: Deltagardiff och manuell deltagarsynk (lärare)

  • Aktör: Lärare
  • Förutsättning: Kopplad kurs med avvikelser mellan Vklass och Classroom.
  • Flöde:
    1. Läraren öppnar fliken Deltagare: diff-tabell "ska vara medlem" (Vklass) vs "är medlem" (Classroom) med roll (TEACHER/STUDENT) och orsak per avvikelse.
    2. Läraren startar "Synka deltagare" → jobb startar asynkront, jobbid returneras direkt, progress och item-resultat visas.
    3. Ett fel för en person visas som item-fel; övriga deltagare synkas klart (Delvis lyckad).
  • Resultat: Diffen är åtgärdad förutom felisolerade items som har orsak + rekommenderad åtgärd.
  • Acceptanskriterier:
    • Orsakskategorier: saknad medlem, ej längre förväntad, fel roll, opt-out, saknad kontomappning, policy-/tjänstblockering, kvot/driftstörning (R-06).
    • Jobb: asynkron start, jobbid, progress, item-resultat, "du kan lämna sidan" (R-07).
    • Felisolering: 1 fel stoppar inte resterande (R-08); resultat = Lyckad/Delvis lyckad/Misslyckad.
    • Opt-out (excludeFromSync) visas med spårbarhet (vem, när, varför).

UC-4: Uppgifter med bevarad CourseWork-mappning (lärare)

  • Aktör: Lärare
  • Förutsättning: Kopplad kurs med uppgifter som synkas till Classroom.
  • Flöde:
    1. Läraren öppnar fliken Uppgifter: tabell med titel, deadline, Topic, publiceringsläge, mappningsstatus, senaste synk, inlämningsstatus och bedömningsstatus (separata).
    2. Läraren redigerar en uppgift (titel/deadline) → dialogen visar att Classroom-kopplingen bevaras.
    3. Läraren kör "Synka om" → omkörning uppdaterar samma CourseWork utan dubblett.
  • Resultat: Mappningen är intakt; ingen dubblett skapas.
  • Acceptanskriterier:
    • Fältmängd: titel, instruktion, deadline, publiceringsläge, Topic, länkar/material (R-09).
    • Redigering nollställer inte kopplingen; byte av Classroom/uppgift kräver explicit åtgärd (R-09).
    • Inlämningsstatus (Ej inlämnad/Inlämnad/Sen/Återlämnad) och bedömningsstatus (Ej bedömd/Utkast/Bedömd/Publicerad) visas som två separata begrepp (R-10).

UC-5: Synkprofil, paus och riktade jobb (admin)

  • Aktör: Org-/IT-admin
  • Förutsättning: Admin har organisationsscope (Nordängens kommun).
  • Flöde:
    1. Admin öppnar Google Classroom-administration: synkprofil per organisation/skola (aktivering, paus, version, objektkategorier, riktning, masterfält, schema).
    2. Admin pausar synk via feature flag → bekräftelsedialog anger att Vklass kärndata inte påverkas.
    3. Admin kör riktade åtgärder (kör pre-flight, synka roster, kör om misslyckade) → asynkron kvittens med jobbid.
  • Resultat: Ändringar slår igenom och auditloggas.
  • Acceptanskriterier:
    • Synkprofilens fält visas och är versionshanterade (R-12).
    • Paus/avstängning utan påverkan på kärndata, med tydlig konsekvenstext (R-13).
    • Riktade åtgärder startar asynkront med jobbid och auditloggas (R-15).

UC-6: Statusöversikt med filter och felklassning (admin)

  • Aktör: Org-/IT-admin
  • Förutsättning: Flera skolor/kurser med olika synkstatus.
  • Flöde:
    1. Admin öppnar statusöversikten: tabell per kurs med scope (org/skola), status, senaste körning, fel per felklass.
    2. Admin filtrerar på skola, felklass och jobbstatus.
    3. Admin öppnar jobbloggen: jobbid, trigger, scope, status, behandlade/lyckade/misslyckade, korrelations-id — utan elevinnehåll.
  • Resultat: Admin felsöker utan elevinnehåll och utan support.
  • Acceptanskriterier:
    • Filter: organisation, skola, kurs, användare, felklass, jobbstatus (R-14).
    • Felklasser enligt § 7-listan med kundvänlig text + rekommenderad åtgärd (R-21).
    • Jobblogg sanerad (R-11); scope-kolumner (R-22).

UC-7: Legacy-backfill i kontrolläge + auditlogg (admin)

  • Aktör: Org-/IT-admin
  • Flöde:
    1. Admin kör legacy-backfill i kontrolläge (dry-run) → resultat: migrerbara kopplingar, osäkra externa id:n (markerade för åtgärd), redan mappade. Ingen skrivning till Google.
    2. Admin öppnar auditloggen: koppla/avkoppla, aktivera/pausa, profiländringar, opt-out, pre-flight, manuella jobb — aktör, roll, tid, scope, åtgärd, resultat, korrelations-id.
  • Resultat: Migreringsläget är känt; alla känsliga händelser är spårbara.
  • Acceptanskriterier: Kontrolläge skriver inte till Google (R-16); auditlogg komplett utan elevinnehåll (R-17).

UC-8: Aggregerad hälsa (rektor)

  • Aktör: Skolledare
  • Flöde: Rektor öppnar integrationsöversikten för Proximaskolan: KPI-kort (kopplade kurser, aktiva synkar, varningar, blockerare) + kurslista med status och senaste körning.
  • Resultat: Skolledaren ser hälsan utan åtkomst till elevdokument i Google.
  • Acceptanskriterier: Aggregerat inom skolåtkomst; inga elevdokumentlänkar (R-18); status med text + etikett (R-02).

UC-9: Elevens uppgiftsvy (elev)

  • Aktör: Elev
  • Flöde: Anna öppnar sina uppgifter: lista med kurs, uppgift, deadline, Classroom-etikett, inlämningsstatus och återkoppling enligt Vklass behörighetsmodell; primär åtgärd "Öppna i Classroom" där arbetet sker där.
  • Resultat: Konsekvent status utan parallella listor.
  • Acceptanskriterier: Konsekventa deadlines/statusar; Classroom-länk tydligt markerad som extern Google-länk; aldrig andra elevers material (R-19).

UC-10: Vårdnadshavarens insyn utan Google (vårdnadshavare)

  • Aktör: Vårdnadshavare
  • Flöde: Eva öppnar Annas uppgifter: planering, uppgift, deadline, inlämningsstatus och sammanfattande återkoppling. Infotext förklarar att inget Google-konto krävs.
  • Resultat: Samlad insyn i Vklass utan Google-beroende.
  • Acceptanskriterier: Ingen Google-inloggning krävs; inga direktlänkar till elevmaterial i Google (R-20); inlämnings- och bedömningsstatus separata (R-10).

Datamodell

Intent-namn från dokument 168 § 5.2 (slutlig SQL-design beslutas i lösningsfasen):

  • GoogleClassroomSyncProfile — customerOrganisationID, schoolID, isEnabled, isPaused, profileVersion, enabledObjects, direction, fieldMasterRules, schedule, updatedBy/At
  • GoogleClassroomCourseMapping — courseID, schoolID, customerOrganisationID, classroomCourseId, alternateLink, ownerUserID, mappingStatus (Active/Paused/Archived/Orphaned), lastSuccessfulSyncAt, lastErrorCode, externalVersion
  • GoogleClassroomRosterState — courseMappingID, userID, expectedRole (TEACHER/STUDENT), actualRole/status, optOut {by, at, reason}, lastResult, diffReason
  • GoogleClassroomCourseWorkMapping — examID, courseID, classroomCourseWorkId, classroomTopicId, alternateLink, state (utkast/publicerad/schemalagd), dueAt, lastSuccessfulSyncAt, submissionStatus, assessmentStatus (separata)
  • GoogleClassroomSyncJob / JobItem — jobID, trigger (Manuell/Schema/Reparation/Pre-flight), scope, status (Köad/Pågår/Lyckad/Delvis lyckad/Misslyckad), counts {processed, succeeded, failed}, correlationId; items: category, ids, operation, result, errorCode/class
  • GoogleClassroomPreflightResult — scope (org/skola/kurs/användare), level (OK/Varning/Blockerare), errorCode, errorClass, message, recommendedAction, technicalDetail, checkedAt, expiresAt
  • GoogleClassroomSyncAudit — actor, role, action, scope, result, correlationId, at
  • Legacy: courses.courseDelegatedResources (JSON, bevaras), GoogleAppsConfig (GoogleAppsUseClassroom, GoogleAppsDomain), GoogleAppsAccount (username/alias), courseParticipants (courseTeacher, endDate, excludeFromSync), exams.examDigitalJSON

Felklasser (R-21): auth-scope, policy-ou, missing-account, missing-mapping, wrong-domain, missing-object, validation, quota, outage, conflict, unknown — alla med stabil felkod (GCR-xxx), kundvänlig text och rekommenderad åtgärd.

  • Lärare: Vänstermeny → kursen Svenska 7A → "Google Classroom" (kursens inställnings-/statusyta). Flikar: Översikt, Deltagare, Uppgifter, Jobblogg.
  • Admin: Adminmeny → Integrationer → Google Classroom. Sektioner: Synkprofil, Statusöversikt, Jobb & logg, Legacy-migrering, Auditlogg.
  • Rektor: Vänstermeny → Skolöversikt → Google Classroom-status.
  • Elev: Vänstermeny → Uppgifter.
  • Vårdnadshavare: Vänstermeny → Barnets uppgifter.
  • index.html är rollväljare med länk till samtliga fem vyer + demofilm.

Tillgänglighetskontrakt (a11y baseline)

  • Dialogmodaler: dialog-connect (koppla kurs, R-03/R-04), dialog-sync-job (deltagarsynk-jobb, R-07), dialog-edit-assignment (redigera uppgift, R-09), dialog-pause-sync (paus-bekräftelse, R-13), dialog-backfill (kontrolläge-resultat, R-16). Alla öppnas via shared window.vklassDialogManager.openDialog(id, opener) — fokus-trap, inert på sidskal, Escape-stängning, fokusåtergång till opener. Ingen lokal DialogManager-klass. Se mockup-accessible-dialog/SKILL.md.
  • Tabs: lärarens kursyta har flikar (Översikt/Deltagare/Uppgifter/Jobblogg) — role=tablist/tab/tabpanel, roving tabindex, piltangenter, aria-selected. Se mockup-accessible-dynamic-ui/SKILL.md.
  • Filter/sök: adminöversiktens filter använder vk-page-filter + trigger med aria-expanded; resultaträkning i aria-live="polite"-region. FILTERS-leaf-mönstret.
  • Toolbar flyouts: sök/snabbval/notiser — aria-expanded synkas med --open-klass via _syncFlyoutAria.
  • Jobbstatus/progress: progressbar med role="progressbar" + aria-valuenow; statusuppdateringar i aria-live="polite"; § 8 kräver skärmläsbar jobbstatus.
  • Form validation: kopplingsdialogens val (skapa/länka + varningsbekräftelse) valideras med inline-fel + aria-describedby. Se mockup-accessible-form-validation/SKILL.md.
  • Skip-links: <a class="skip-link" href="#main-menu"> + <a class="skip-link" href="#main-content"> + <main id="main-content" tabindex="-1">.
  • Status ej enbart färg: alla status-badges har text + ikon (R-02).
  • Keyboard test scope: UC-2 (dialog), UC-3 (tabb + jobbdialog), UC-4 (redigeringsdialog), UC-5 (paus-dialog), UC-6 (filter).

Bilder/sketcher

Inga referensbilder — implementera utifrån Vklass V2 Athena Design System (.cursor/rules/vklass-v2-*.mdc, documentation/vklass-design-system-complete.md). screenshotMatchingStrategy: "reference-only".

Öppna frågor

  • Q-01: Bedömnings-UI (matris/omdöme) byggs inte — endast bedömningsstatus som badge (senare leverans § 5.6–5.7).
  • Q-02: Google-panel/add-on byggs inte (senare leverans § 3.3; teknikval öppet § 13.7).
  • Inga blockerande frågor för v1.