Skip to Content
Technical docsArchitecture

Architecture

┌─────────────┐ portal link ┌──────────────────┐ │ Parent │ ───────────────► │ /portalaccess/… │ └─────────────┘ └────────┬─────────┘ │ sets upload_access cookie ┌──────────────────┐ │ Upload page / │ │ /api/upload* │ └────────┬─────────┘ │ Graph upload ┌─────────────┐ admin OAuth ┌──────────────────┐ │ Admin │ ───────────────► │ /setup + Redis │ │ (/setup) │ │ config + links │ └─────────────┘ └────────┬─────────┘ ┌────────────────────────┼────────────────────────┐ ▼ ▼ ▼ Upstash Redis OneDrive (Graph) Azure Email links + config uploaded video notification
Redis keyContentsTTL
link:{uuid}createdAt, childName, edc, expiresAt, optional usedAtSet to link expiry at creation; kept until dismissed after consume
app:configPartial config overridesNone

Parent-facing checks (/portalaccess/[token])

ResultBehavior
Missing / expired / usedRedirect to /link-expired
Still in bufferRedirect to pending countdown with availableAt
ActiveSet portal cookie and redirect to /

Important: opening the link does not consume it. Consumption happens only after a successful upload finalize.

Filename derivation

At upload time the server builds:

GMA Video {Child Name} {DD.MM.YYYY}_{ageWeeks}{extension}

Age (weeks) = whole weeks from EDC → date recorded (lib/age.ts). Calculation is server-side; the parent UI does not preview age.

Authentication cookies

CookiePurposeNotes
onedrive_pkcePKCE code verifierHttpOnly, short-lived (~10 min)
onedrive_auth_flowsetup | admin | upload-accessHttpOnly, short-lived
upload_accessSigned portal or admin sessionHttpOnly; Secure in production; ~14 days

Cookie HMAC secret resolution: UPLOAD_ACCESS_SECRET → else UPSTASH_REDIS_REST_TOKEN → else a dev-only fallback (do not rely on fallback in production).

Portal vs admin payload

  • Portal: { type: "portal", token, exp }
  • Admin: { type: "admin", username, exp } — username must remain allowlisted

There is no Next.js middleware.ts; auth is enforced inside route handlers.

Last updated on