Skip to content

Slice 4 (Module 02): Doctor "Shared with me" view + document download #12

Description

@mGasiorek998

What to build

Give doctors a view of all documents shared with them and the ability to download any shared file. Expose the doctor-facing component as a named export so Module 04 (appointments) can embed it without reimplementing any document logic.

  • getSharedWithMe use case: returns documents shared with the authenticated doctor, grouped by owning patient (patientId, patientDisplayName, documents[]).
  • downloadDocument use case: verifies a document_shares row exists for (documentId, doctorId) before streaming — 403 ACCESS_DENIED if absent. Streams via createReadStream (no full-file buffering).
  • GET /documents/shared-with-me → 200 + Array<{ patientId, patientDisplayName, documents: Array<{ id, filename, mimeType, size, uploadedAt }> }> behind requireAuth() + requireRole(['doctor']). Note: this path must be registered before GET /documents/:id/file in the Hono router.
  • GET /documents/:id/file → 200 + binary stream (Content-Type: stored mimeType, Content-Disposition: attachment; filename="<original>") behind requireAuth() + requireRole(['doctor']). Returns 403 ACCESS_DENIED if not shared with this doctor; 404 DOCUMENT_NOT_FOUND if document does not exist.
  • Fill in these two endpoints in packages/contracts/src/documents.ts.
  • SharedDocumentsList React component (named export): self-contained, no required props, renders grouped documents with download links using the useSharedDocuments hook.
  • useSharedDocuments TanStack Query hook (named export): calls GET /documents/shared-with-me.
  • Both exports live under apps/web/src/features/documents/ and are importable by Module 04 without any document logic being reimplemented there.

Acceptance criteria

  • GET /documents/shared-with-me returns 200 with documents grouped by patient when shares exist; returns [] when no documents are shared with the doctor.
  • GET /documents/:id/file streams the file with correct Content-Type and Content-Disposition: attachment; filename="<original>" headers when the document is shared with the calling doctor.
  • GET /documents/:id/file returns 403 { error: "ACCESS_DENIED", ... } when no document_shares row exists for the (documentId, doctorId) pair; zero file bytes are written to the response.
  • GET /documents/:id/file returns 404 { error: "DOCUMENT_NOT_FOUND", ... } for an unknown document id.
  • Both endpoints return 401 without a valid JWT and 403 with a patient JWT.
  • SharedDocumentsList renders the grouped document list when imported and rendered in isolation (Vitest component test against a mocked contract).
  • useSharedDocuments is a named export callable from outside the documents feature folder.
  • pnpm verify exits 0.

User stories covered

Blocked by

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    afkEligible for the main agent looppriority:2Priority 2qa-readyPR opened, awaiting human QAsliceVertical tracer-bullet slice

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions