Architecture outcome
Band Licence uses one account service and one school-data source of truth across the browser, installable web app, iPhone, iPad and Android.
Current status: a production-shaped web client and unsigned native foundations exist. The native foundations are not yet complete teacher apps and are not store-ready.
The native projects currently prove the security boundary: protected sign-in, secure token storage, server session bootstrap, verified-link routing, camera-only local QR/Code 128 scanning and operating-system share/print handoffs. They do not yet implement attendance, scheduling, student management, offline sync, subscriptions or native PDF report workflows.
Current-versus-future capability map
| Capability | Web/PWA now | iOS/iPadOS foundation now | Android foundation now | Release work still required |
|---|---|---|---|---|
| Shared account | Implemented | Implemented bootstrap | Implemented bootstrap | Verified production account recovery and device tests |
| School roles | Server enforced | Session displays accessible schools | Session displays accessible schools | Native school selection and full route-level tests |
| Attendance and scheduling | Implemented in web | Not implemented natively | Not implemented natively | Versioned business APIs and native workflows |
| QR and Code 128 scan | Local browser scan where supported | Local AVFoundation scan | Local CameraX/ML Kit scan | Permission recovery, duplicate-scan control and workflow integration |
| Verified links | Server endpoints fail closed | Entitlement scaffold | autoVerify intent scaffold | Final domain, signed identities and physical-device verification |
| Secure session | Secure web cookie | Device-only Keychain | Keystore key plus AES-GCM ciphertext | Runtime leakage and revocation tests |
| Share/print | Browser/PDF workflows | Connection-summary system handoff only | Connection-summary system handoff only | Real report/PDF handoff |
| Offline | Public shell only | No school-data cache | No school-data cache | Deliberate offline conflict model before any expansion |
| Microphone | Teacher-armed Lesson Note assistance exists only in the explicitly enabled web deployment, using temporary processing through the authenticated loopback engine on the app host | No native microphone permission | No native microphone permission | Keep absent from first native release until native-specific approval and device evidence exist |
| Push notifications | Not implemented | Not implemented | Not implemented | Consent, school approval, delivery provider and privacy review |
| Payments | Not implemented | Not implemented | Not implemented | Subscription decision and store-policy review |
No release material may shorten this table to “native complete”. Static foundation checks do not replace signed builds or usable feature completion.
System boundaries
Shared service
The server owns:
- account credentials, verification, lockouts and session revocation;
- school membership and Administrator, Teacher and Read-only roles;
- student records, attendance, timetables, progress and audit history;
- subscription entitlement if it is introduced later;
- versioned API policy;
- deletion, correction and retention workflows; and
- the authoritative deployment and capability state.
Native client
The native app may own:
- ephemeral sign-in state and PKCE verifier;
- one protected revocable session token;
- transient camera frames used for local code decoding;
- non-sensitive interface preferences; and
- temporary operating-system share/print presentation.
The native app must not own:
- a second account or school database;
- permanent student or attendance copies;
- a device-only entitlement;
- passwords;
- signing secrets or API client secrets;
- retained camera frames;
- background location;
- advertising identifiers; or
- unapproved audio, video or analytics data.
Installable web app
The existing service worker may cache only public shell/static files and the offline page. Authenticated pages, API responses, student records, attendance, reports and school data must remain no-store.
Implemented client contract
Public bootstrap
GET /api/client/v1/config returns contract version 2 and:
- app name and configured origin;
- deployment label;
- sign-in, exchange, session, account and deletion paths;
- S256 support and the two-minute handoff lifetime;
- approved verified-link paths; and
- non-sensitive capability flags.
It must never return users, schools, students, attendance or credentials.
Native authentication
The app uses the system browser and the contract in Native Sign-in Handoff. The handoff is single-use, bound to S256 PKCE, state, platform and app version.
Session bootstrap
GET /api/client/v1/session returns:
- account ID, display name and email;
- accessible school IDs, names, slugs and roles;
- deployment label; and
- non-sensitive client capabilities.
It is no-store and returns 401 for a signed-out user or pilot fallback. DELETE revokes the presented native Bearer session.
This endpoint does not return student, attendance or timetable data. New native features must use explicitly versioned, school-scoped APIs with the same server-side access checks as the web app.
API expansion rules
Before adding a native business endpoint:
- Define the user task and minimum returned fields.
- Reuse the existing school access helper; never rely on a school ID selected only by the client.
- Require the correct role for every read or mutation.
- Return no more personal information than the screen needs.
- Use no-store for school or account data.
- Add an idempotency strategy for retryable mutations.
- Record the same audit event as the equivalent web action.
- Document contract versioning and the oldest supported app version.
- Test cross-school object IDs and revoked roles.
- Add retention, correction and deletion mapping before release.
Do not expose existing internal server actions directly as an undocumented mobile API.
Network and consistency model
The first native release is online-only for authenticated school work:
- the server is authoritative;
- reads refresh after sign-in, school switch and foreground return;
- mutations succeed only after a server acknowledgement;
- a timeout is not treated as proof that a mutation failed;
- retryable mutations need a client-generated idempotency key;
- an expired or revoked session returns the user to sign-in;
- no optimistic offline attendance queue is permitted; and
- the user receives a clear connection state and a safe retry action.
Attendance is high-consequence data. Any future offline queue needs a separate design for duplicate scans, ordering, device clock drift, conflict review, revoked roles, lost devices and school-data encryption. It must not be added as a convenience cache.
Platform implementation
Apple foundation
Current code in mobile/ios:
- SwiftUI application targeting iPhone and iPad;
- ASWebAuthenticationSession for external-browser sign-in;
- random state and verifier generated with SecRandomCopyBytes;
- S256 with CryptoKit;
- exact HTTPS host/path/state validation;
- session stored as a generic-password Keychain item with AfterFirstUnlockThisDeviceOnly accessibility;
- local AVFoundation QR and Code 128 decoding;
- Associated Domains entitlement from protected build configuration; and
- fail-closed placeholder origin.
Before release:
- set the real development team, bundle identifier and associated domain;
- add production and staging configurations with visibly different identities;
- confirm Keychain behaviour after reinstall, restore and device transfer;
- stop the capture session when backgrounded and make permission denial recoverable;
- add accessible scan status, manual code fallback where safe, haptics and duplicate-scan suppression;
- implement actual native user workflows;
- create and validate PrivacyInfo.xcprivacy for the app and every included SDK;
- add UI and accessibility tests; and
- archive, sign and test the exact candidate on real iPhone and iPad hardware.
Android foundation
Current code in mobile/android:
- Kotlin/Compose app with minSdk 26, compileSdk 36 and targetSdk 36;
- Chrome Custom Tabs for external-browser sign-in;
- SecureRandom state and verifier;
- S256 with the platform message digest;
- exact host/path/state validation;
- session ciphertext in private SharedPreferences, protected by an AndroidKeystore AES-GCM key;
- android:allowBackup false and cleartext traffic disabled;
- CameraX plus local ML Kit QR and Code 128 decoding;
- autoVerify HTTPS intent filter; and
- fail-closed placeholder origin.
Before release:
- set the final application ID, host, signing and Play App Signing ownership;
- separate staging and production variants;
- confirm the app uses the installed Play App Signing certificate fingerprint, not only the upload key;
- add robust permission-denied and permanent-denial UI;
- suppress duplicate scans and stop analysis while backgrounded;
- inspect the compiled manifest and App Bundle for unintended permissions, components and SDKs;
- complete the Google Play SDK/data-safety inventory, including ML Kit;
- test adaptive phone/tablet layouts, rotation, split-screen and large text;
- implement actual native user workflows;
- add Compose UI, accessibility and instrumented tests; and
- test the release App Bundle from Play internal testing on real phone and tablet hardware.
Build and environment strategy
Use three deliberately separate environments:
| Environment | Data | Identity | Distribution | Native links |
|---|---|---|---|---|
| Development | Fictional local data | Debug ID/signing | Developer devices | Disabled or debug-only |
| Staging/account beta | Fictional or approved test school | Separate staging app identity | TestFlight/Play internal or closed | Staging domain only |
| Production | Approved production data | Final production identity | Store release | Production domain only |
The web runtime origin comes from server-only BAND_LICENCE_APP_URL. The current native origins are injected at build time through the Apple build setting or Android Gradle property. Therefore each native archive must record the exact origin and cannot be promoted between staging and production without verifying that configuration.
Never place passwords, API secrets, signing private keys or student data in source-controlled configuration. Store ownership and recovery must belong to the approved organisation, not one developer’s personal account.
Permission budget
| Permission/capability | First native release | Conditions |
|---|---|---|
| Camera | Allowed | QR/Code 128 only; local frames; just-in-time explanation; denial fallback |
| Network | Required | Trusted HTTPS only |
| Associated Domains/App Links | Required | Approved paths only |
| Keychain/Keystore | Required | Session token only |
| Microphone | Not included | Separate lesson-note privacy and school approval |
| Photo library | Not included | Student photos are prohibited |
| Location | Not included | No current purpose |
| Contacts/calendar | Not included | No current native workflow or approval |
| Notifications | Not included | Future explicit opt-in and child-safety review |
| Advertising ID/tracking | Prohibited | No advertising or tracking |
| Broad file access | Not included | Use operating-system document/share controls only if added |
Permission text must describe actual shipped behaviour. Do not mention a future feature to justify present access.
Accessibility acceptance
Test each common task—first launch, sign-in, school selection, scanning, permission recovery, account details, sign-out and error recovery—with:
- VoiceOver and Voice Control on iPhone and iPad;
- TalkBack and Switch Access on Android phone and tablet;
- text at least 200 percent where the platform supports it;
- portrait, landscape, split-screen and keyboard navigation;
- Reduce Motion or equivalent;
- high contrast and colour differentiation;
- screen zoom and small/large display sizes; and
- plain-language status announcements.
Temporary messages must be announced. Controls need meaningful labels and adequate touch targets. Focus must not disappear when returning from the system browser or camera permission sheet.
Do not claim Apple Accessibility Nutrition Label support unless all common tasks meet Apple’s criteria on each claimed device type.
Privacy and child-safety architecture
- The app is school/teacher controlled; it does not create public child profiles or student-to-student communication.
- Student photos remain prohibited.
- QR card routes remain token-bound and narrow: progress and attendance are read-only, while unlocked QR profile sessions have only the documented practice-timer/tracking, sight-reading-result and friend-choice writes.
- The camera decoder must not retain, upload or put frames into analytics.
- Store screenshots and review data use fictional identities only.
- No analytics, advertising, tracking, third-party chat or cloud media service may be introduced without a fresh school, privacy and store declaration review.
- The future Student role (product label Player Account) and the separate Parent/Carer role remain unavailable until their access, consent, support and deletion models are approved. Student and Player are not two account roles.
- Background execution must not silently collect school data.
Mobile security verification
Use the OWASP MASVS categories as a release test index:
- STORAGE: token location, device backups, logs, screenshots and pasteboards;
- CRYPTO: random generation, Android AES-GCM and platform cryptography;
- AUTH: browser handoff, PKCE, revocation, roles and reauthentication;
- NETWORK: trusted TLS, no cleartext, redirects and proxy behaviour;
- PLATFORM: exported components, verified links and permission prompts;
- CODE: dependency review, release build, debug artefacts and error handling;
- RESILIENCE: tamper and integrity risk decision proportionate to the school context; and
- PRIVACY: minimal permissions, no undeclared SDK collection and accurate store declarations.
The static command:
pnpm native:foundation-checkconfirms twelve repository properties. It is not a MASVS assessment or a penetration test.
Release and rollback
Native client release order:
- Deploy a backward-compatible server contract.
- Observe web production stability.
- Enable the contract in staging only.
- Test signed native candidates in TestFlight and Play internal testing.
- Complete device, accessibility, privacy and store evidence.
- Release to a limited production cohort.
- Expand gradually while monitoring sign-in, 401/429 rates, crashes and support reports.
If a native defect appears:
- disable native links/sign-in server-side when authentication or link safety is affected;
- revoke compromised sessions;
- stop staged store rollout;
- submit a corrected binary;
- keep the previous server contract while supported app versions remain in use; and
- never use a destructive database rollback merely to compensate for an app binary.
Removing an app from sale does not remove installed copies. Server contracts need explicit minimum-version and retirement policy before public release.
Decision records
MCA-001 — One backend, no device school database
All clients use the same account, roles, entitlements and school records. This prevents divergent truth and avoids placing a full student database on a lost device.
MCA-002 — Native value, not a website wrapper
Native clients use platform sign-in, scanning, secure storage and system handoffs. Store release waits until core tasks provide genuine useful native workflows.
MCA-003 — Online-first authenticated workflows
Offline school-data caching is deferred until conflict resolution, encryption, revocation and retention are formally designed.
MCA-004 — Minimal permission first release
Only camera access is currently justified. Microphone, notifications, files, contacts, calendar and other protected resources need separate approval.
MCA-005 — Versioned expansion
New native tasks use /api/client/v1 or a deliberate successor, not internal page contracts. Breaking changes require a new version or a measured compatibility window.
Release evidence
Retain privately:
- source commit and artifact hashes;
- dependency lockfile and software bill of materials;
- platform configuration and final origin;
- signing identity ownership and recovery procedure;
- API contract tests and server compatibility matrix;
- real-device functional, security and accessibility results;
- permission and compiled-manifest inspection;
- device log, crash and backup leakage review;
- privacy manifest, Apple App Privacy and Google Data safety reconciliation;
- child-safety and school approval;
- store reviewer account/instructions with fictional data; and
- staged rollout, monitoring and rollback owner.
Related guides
- Native Sign-in Handoff
- Lesson Note Transcription Architecture
- Store Release Evidence
- App Store and Play Store Readiness
Official references
Checked 12 August 2026. Recheck immediately before release: