Project: doctolib-doctolib · Branch: .invalid · Mode: ` · **Model:**claude-sonnet-4-6`
Stats: 1 user messages, 29 tool calls, tools used: Read, Bash.
Conversation
Turn 1 — User
Please review the implementation plan at: /Users/USER/Library/CloudStorage/<REDACTED>/My Drive/ai-artifacts/nhr-document-list/observability/implementation-plan.md
This is an observability strategy plan for the National Health Records (NHR) adapter layer in the Doctolib monorepo at /Users/USER/workspace/doctolib/doctolib.
Context to understand the plan:
- The adapter layer is at packages/@doctolib/national-health-records/
- Key file: packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.ts — implements NhrAdapter interface
- Key file: packages/@doctolib/national-health-records/src/hooks/useDmpNhr.ts — wires up the adapter into a React hook
- The plan proposes adding a NhrAdapterWithObservability decorator class and helper nhrMonitoring.ts in a new src/observability/ subfolder
- sendMonitoringEvent from monolith_DEPRECATED/services/monitoring is the Datadog event sender used across the codebase
What I need from you:
1. Review the plan for adherence to Doctolib's UpFront frontend architecture patterns
2. Check the TypeScript patterns proposed (decorator pattern, typed details objects)
3. Evaluate whether the placement (subfolder vs new package) makes sense architecturally
4. Check if the useDmpNhr.ts modification follows React hook patterns correctly
5. Identify any anti-patterns, naming issues, or missing concerns
6. Provide specific, actionable feedback — not just "looks good"
Read the plan file and the key source files listed above before reviewing. Return a structured list of issues found (if any), each with a clear recommendation for how to fix it.
Turn 1 — Assistant
I'll read the implementation plan and the key source files before reviewing.
Tools used:
Read:/Users/USER/Library/CloudStorage/<REDACTED>/My Drive/ai-artifacts/nhr-document-list/observability/implementation-plan.md
Tool results:
→ result (ok): 1 # NHR Adapter Observability — Implementation Plan
2
3 ## Context
4
5 The National Health Records (NHR) feature is built on a 3-layer architecture:
6
7 | Layer | Package | Ownership |
8 |---|---|---|
9 | 1 — Local (France DMP) | @doctolib/dmp | @doctolib/moose — read-only |
10 | 2 — Adapter | @doctolib/national-health-records | @doctolib/fire |
11 | 3 — Generic interface | @doctolib/tpf-national-health-records | @doctolib/fire |
12
13 The adapter layer (`@doctolib/national-health-
…(truncated, 19463 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.ts
Tool results:
→ result (ok): 1 DmpApi, 2 DmpAuthor, 3 DmpDocument, 4 DmpDocumentContent, 5 SearchProps, 6 SearchResult as DmpSearchResult, 7 } from '@doctolib/dmp' 8 import { DmpApiError, DOCUMENT_STATUS, DOCUMENT_VISIBILITY, getPatientInsForDMP } from '@doctolib/dmp' 9 import { isUnstructured } from '@doctolib/cda/types/UnstructuredBody' 10 import { isStructured } from '@doctolib/cda/types/StructuredBody' 11 import type { Patient } from 'monolith_DEPRECATED/types/doctor/api/Patient' 12 import type { 13 NhrAdapt …(truncated, 9700 more chars)
Now let me read the useDmpNhr.ts hook and explore the package structure.
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/hooks/useDmpNhr.ts
Tool results:
→ result (ok): 1 import { useMemo } from 'react' 2 import type { Patient } from 'monolith_DEPRECATED/types/doctor/api/Patient' 3 import { DmpApiImpl as DmpApi, useDmpSetUp } from '@doctolib/dmp' 4 import { createNhrService } from '@doctolib/tpf-national-health-records' 5 import { useDocumentCategorizationFacetsIndex } from 'engines/document_categorization/queries/document_categorization/facets' 6 import { DmpNhrAdapter } from '../business/adapters/DmpNhrAdapter' 7 import type { UseNhrOperations } from './useNa …(truncated, 812 more chars)
Tools used:
Bash:find /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src -type f | sort
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.test.ts /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.ts /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/parseHl7DateToIso.test.ts /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/parseHl7DateToI …(truncated, 5619 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/index.ts
Tool results:
→ result (ok): 1 export { useNationalHealthRecords, type UseNhrOperations } from './hooks/useNationalHealthRecords' 2 export { useDmpNhr } from './hooks/useDmpNhr' 3 export { useNhrDocumentListVariant } from './variants/useNhrDocumentListVariant' 4 export type { DocumentSearchOptions, NhrDocumentListVariant } from './variants/types' 5 export { actionsBuilder, type NhrActionsBuilder } from './business/builders/actionsBuilder' 6 export { useGetDocumentsContent } from './hooks/useGetDocumentsContent' 7 export { u …(truncated, 650 more chars)
Tools used:
Bash:cat /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/package.json
Tool results:
→ result (ok): { "name": "@doctolib/national-health-records", "version": "1.0.0", "publishConfig": { "registry": "https://doctolib-580698825394.d.codeartifact.eu-west-1.amazonaws.com/npm/npm-internal/" }, "repository": { "type": "git", "url": "git+https://github.com/doctolib/doctolib.git" }, "keywords": [ "upfront", "modular frontend", "in-monolith-package" ], "engines": { "node": ">= 24.8.0", "npm": ">= 11.6.0" }, "author": "@doctolib/fire", "license": " …(truncated, 1101 more chars)
Tools used:
Bash:grep -r "sendMonitoringEvent" /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/ 2>/dev/null | head -20
Tool results:
→ result (ok): (Bash completed with no output)
Tools used:
Bash:grep -r "monolith_DEPRECATED/services/monitoring" /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/ --include="*.ts" --include="*.tsx" -l 2>/dev/null | head -20
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/secure_messaging_inbox/src/components/doctor/desktop/shared/MailModal/MailModalBody/PatientMailModalBody.test.tsx /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/secure_messaging_inbox/src/components/doctor/desktop/shared/MailModal/MailModalBody/PatientMailModalBody.tsx /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/documents-ui/src/helpers/monitoring/documentEncryptionMonitoring.test.ts /Users/USER/workspace/docto …(truncated, 2393 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/documents-ui/src/helpers/monitoring/documentEncryptionMonitoring.ts
Tool results:
→ result (ok): 1 import { sendMonitoringEvent } from 'monolith_DEPRECATED/services/monitoring'
2 import { isFeatureEnabled } from '@doctolib/variation-management/legacy'
3 import type { ShareWith } from '@doctolib/deepwater_core/public'
4 import type { EncryptableDocumentField, DocumentEncryptionFeature } from '../types'
5
6 interface FormDataInspectionResult {
7 hasTankerEncryptedFile: boolean
8 hasClearTextFile: boolean
9 hasTankerEncryptedMetadata: boolean
10 hasClearTextMetadata: boolean
11 }
12
…(truncated, 3218 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/packages/@doctolib/e_rezept/src/helpers/sendERezeptMonitoringEvent.ts
Tool results:
→ result (ok): 1 import { sendMonitoringEvent } from 'monolith_DEPRECATED/services/monitoring'
2
3 export function sendERezeptMonitoringEvent({
4 name,
5 start,
6 fulfillmentCount,
7 itemType,
8 }: {
9 name: string
10 start: number
11 itemType: string
12 fulfillmentCount?: number
13 }) {
14 const duration = performance.now() - start
15 const details: Record<string, string | number> = {
16 item_type: itemType,
17 avg_duration: duration,
18 }
19
20 if (fulfillmentCount !== undef
…(truncated, 122 more chars)
Tools used:
Bash:find /Users/USER/workspace/doctolib/doctolib/packages/@doctolib -type d -name "observability" 2>/dev/null
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/siilo_ui/src/hooks/observability
Tools used:
Bash:ls /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/
Tool results:
→ result (ok): business components hooks index.ts locales mocks types variants
Tools used:
Bash:ls /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/siilo_ui/src/hooks/observability/
Tool results:
→ result (ok): helpers index.ts types.ts usePatientFormTracking.ts useSiiloAccountTracking.ts useSiiloAttachmentTracking.ts useSiiloBaseTracking.ts useSiiloChannelTracking.test.ts useSiiloChannelTracking.ts useSiiloConversationTracking.test.ts useSiiloConversationTracking.ts useSiiloDoctolibPushTracking.ts useSiiloDocumentShareTracking.ts useSiiloFullscreenTracking.ts useSiiloGroupTracking.test.ts useSiiloGroupTracking.ts useSiiloMonitoringEvent.ts useSiiloNetworksTracking.ts useSiiloObservability.ts useSiiloP …(truncated, 267 more chars)
Tools used:
Bash:grep -r "NhrResultStatus" /Users/USER/workspace/doctolib/doctolib/packages/ --include="*.ts" -l 2>/dev/null | head -5
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.ts
Tools used:
Bash:find /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/tpf-national-health-records -name "*.ts" | xargs grep -l "NhrResultStatus\|NhrResult\b" 2>/dev/null | head -5
Tool results:
→ result (ok): bfs: error: /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/tpf-national-health-records: No such file or directory.
Tools used:
Bash:grep -r "NhrResultStatus\|'partial success'\|partial_success" /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/tpf-national-health-records/ --include="*.ts" 2>/dev/null | head -20
Tool results:
→ result (ok): (Bash completed with no output)
Tools used:
Bash:find /Users/USER/workspace/doctolib/doctolib -path "*/tpf-national-health-records/src" -type d 2>/dev/null | head -5
Tools used:
Bash:find /Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records -name "*.d.ts" 2>/dev/null | head -5
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records/dist/index.d.ts /Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records/dist/business/nhr-service-factory.d.ts /Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records/dist/business/types/api.d.ts /Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records/dist/business/types/service.d.ts /Users/USER/workspa …(truncated, 105 more chars)
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records/src /Users/USER/workspace/doctolib/doctolib/.yalc/@doctolib/tpf-national-health-records/src
Tools used:
Bash:grep -r "NhrResultStatus\|NhrDocumentSearchResult\|status.*partial" /Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records/dist/ --include="*.d.ts" 2>/dev/null …(truncated, 11 more chars)
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records/dist/index.d.ts:export type { NhrResult, NhrResultStatus, NhrDocumentSearchParams, NhrDocumentSearchProps, NhrDocumentSearchResult, NhrGetDocumentsContentParams, NhrGetDocumentsContentProps, NhrDocumentContentResult, NhrDocumentMetadataUpdatePayload, NhrDocumentMetadataUpdateParams, NhrDocumentMetadataUpdateProps, NhrDocumentMetadataUpdatePayloadResult, NhrDocumentMetadataUpdateResult, NhrServiceInformatio …(truncated, 2632 more chars)
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records/dist/business/types/api.d.ts
Tool results:
→ result (ok): 1 import type { DateRange, NhrDocument, NhrDocumentFile } from '#business/types/document'; 2 import type { NhrPatientInformation } from '#business/types/participant'; 3 export type NhrResultStatus = 'success' | 'skipped' | 'error' | 'partial success'; 4 export type NhrResult = { 5 status: NhrResultStatus; 6 message?: string; 7 code?: string; 8 }; 9 export type NhrDocumentSearchParams = { 10 formats?: string[]; 11 categories?: string[]; 12 status?: string; 13 serviceSt …(truncated, 1627 more chars)
Tools used:
Bash:grep -r "ti_connect\|ti-connect" /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/ --include="*.ts" -l 2>/dev/null | head -5
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/secure_messaging_inbox/src/components/doctor/desktop/de/SignatureVerificationButton/useVerifySignature.ts /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/e_rezept/src/business/useERezeptSignAndSendFromDwl.ts /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/e_rezept/src/business/useERezeptSignAndSend.test.ts /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/e_rezept/src/business/useERezeptSignAndSendFromDwl.t …(truncated, 112 more chars)
Tools used:
Bash:grep -rn "partial.success\|partial_success" /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/ 2>/dev/null | head -10
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.ts:265: status = 'partial success' /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.test.ts:700: it('should return partial success when one payload succeeds and one fails', async () => { /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapt …(truncated, 66 more chars)
Tools used:
Bash:grep -n "NhrResult\b" /Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records/dist/business/types/api.d.ts
Tool results:
→ result (ok): 4:export type NhrResult = { 23:export type NhrDocumentSearchResult = NhrResult & { 54:export type NhrDocumentMetadataUpdatePayloadResult = NhrResult & { 59:export type NhrDocumentMetadataUpdateResult = NhrResult & {
Tools used:
Bash:grep -rn "code.*apiErrorCode\|apiErrorCode" /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/ 2>/dev/null | head -10
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.ts:181: code: apiResponse.error.apiErrorCode, /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.test.ts:28: apiErrorCode?: string /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/src/business/adapters/DmpNhrAdapter.test.ts:189: apiErrorCode: 'DMPAccessDeniedB …(truncated, 249 more chars)
Now I have enough information to write a thorough, structured review. Let me also quickly check one more thing about the NhrResult.code type and the status field in the plan versus the actual type.
Tools used:
Bash:grep -n "documents_count\|result.documents\b" /Users/USER/workspace/doctolib/doctolib/node_modules/@doctolib/tpf-national-health-records/dist/business/types/api.d.ts 2>/dev/null
Tools used:
Bash:grep -rn "propertyName.*filter\|\.filter.*Boolean\|filter(Boolean)" /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/ 2>/dev/null | head -5
Tool results:
→ result (ok): (Bash completed with no output)
Tool results:
→ result (ok): (Bash completed with no output)
Tools used:
Bash:grep -rn "tsconfig\|paths\|#business\|#hooks\|#helpers" /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/tsconfig.json 2>/dev/null || cat /Users/USER/worksp …(truncated, 90 more chars)
Tool results:
→ result (ok): /Users/USER/workspace/doctolib/doctolib/packages/@doctolib/national-health-records/tsconfig.json:2: "extends": "../../../tsconfig.base.json",
Tools used:
Bash:grep -n "paths\|#business\|#hooks\|#helpers\|#data\|#components" /Users/USER/workspace/doctolib/doctolib/tsconfig.base.json 2>/dev/null | head -30
Tool results:
→ result (ok): 6: "paths": {
Tools used:
Read:/Users/USER/workspace/doctolib/doctolib/tsconfig.base.json(1–50)
Tool results:
→ result (ok): 1 { 2 "compilerOptions": { 3 "target": "esnext", 4 "useDefineForClassFields": true, 5 "plugins": [{ "name": "typescript-plugin-css-modules" }], 6 "paths": { 7 "engines/aati/": ["./engines/aati/app/assets/javascripts/"], 8 "engines/activity_page/": ["./engines/activity_page/app/assets/javascripts/"], 9 "engines/anonymous_funnel/": ["./engines/anonymous_funnel/app/assets/javascripts/"], 10 "engines/appointment_request/*": ["./engines/appointment_requ …(truncated, 3753 more chars)
Now I have a complete picture to deliver a thorough review. Here is the full structured assessment:
Architecture Review: NHR Adapter Observability Plan
Critical Issues (must fix)
1. src/observability/ subfolder violates the UpFront layer taxonomy
The plan proposes packages/@doctolib/national-health-records/src/observability/ as a new top-level subfolder alongside src/business/, src/hooks/, src/helpers/, etc. This is an architecture violation.
The UpFront rules define what each top-level subfolder under src/ represents: business/ for pure domain logic, data/ for repository hooks, hooks/ for shared custom hooks, helpers/ for stateless utilities, components/ for React components. "Observability" is not a layer — it is a cross-cutting concern that maps to an existing layer.
NhrAdapterWithObservability is a pure class with no React imports and no side effects beyond calling sendMonitoringEvent. It belongs in src/business/. nhrMonitoring.ts is a collection of stateless helper functions — it belongs in src/helpers/.
Correct placement:
- /src/business/adapters/NhrAdapterWithObservability.ts — colocated with DmpNhrAdapter.ts, its only current consumer
- /src/helpers/nhrMonitoring.ts — flat file alongside other helpers (no subdirectory, consistent with the rule against subdirectories in src/helpers/)
2. NhrResponseDetails.status typed as string instead of NhrResultStatus
The plan types status as string in NhrResponseDetails. The actual domain type is NhrResultStatus = 'success' | 'skipped' | 'error' | 'partial success' from @doctolib/tpf-national-health-records. Using a bare string discards compile-time validation and makes the type misleading — callers can pass any string, including values that will never appear in Datadog queries.
Fix:
import type { NhrResultStatus } from '@doctolib/tpf-national-health-records'
type NhrResponseDetails = {
// ...
status?: NhrResultStatus
// ...
}
3. error_code typed as string | number | undefined but NhrResult.code is typed string | undefined
The plan's event schema says error_code can be a number with the justification "e.g., DMP API error code". However, the actual NhrResult interface in @doctolib/tpf-national-health-records defines code as string | undefined — not a number. The DmpNhrAdapter itself assigns code: apiResponse.error.apiErrorCode which is also typed as string in the test stubs. The number branch in the union is a phantom type that will never be hit and will confuse future readers.
Fix: type error_code as string | undefined to match the domain.
4. status: 'partial_success' in event schema conflicts with actual domain value 'partial success'
The event design table (section "Event Design") lists 'partial_success' as a valid status value. The actual NhrResultStatus domain type uses 'partial success' (with a space, not an underscore). The decorator passes result.status directly — so the value sent to Datadog will be 'partial success', not 'partial_success'. The plan's schema documentation is inconsistent with the implementation. Pick one and make both the documentation and the type agree. If the intent is to normalize to underscore format for Datadog, add an explicit mapping step and document it. If not, correct the schema table.
Warnings (should fix)
5. Test file location does not follow UpFront colocated test convention
The plan proposes:
src/observability/__tests__/NhrAdapterWithObservability.test.ts
The UpFront convention is to colocate tests next to their source file, not inside a __tests__/ subdirectory. Every existing test in this package follows that pattern:
- /src/business/adapters/DmpNhrAdapter.test.ts
- /src/business/adapters/parseHl7DateToIso.test.ts
- /src/business/utils/findFacetForCDAType.test.ts
With the corrected placement from issue #1, the test file should be:
/src/business/adapters/NhrAdapterWithObservability.test.ts
6. NhrAdapterWithObservability is exported from DmpNhrAdapter in src/index.ts but not mentioned in the export plan
The current src/index.ts already exports DmpNhrAdapter directly:
export { DmpNhrAdapter } from './business/adapters/DmpNhrAdapter'
The plan is silent on whether NhrAdapterWithObservability should also be re-exported from src/index.ts. Since the decorator is wired internally in useDmpNhr.ts and never consumed by package consumers, it should NOT be added to src/index.ts. The plan should make this explicit to avoid an accidental export being added by the implementer.
7. useDmpNhr.ts wiring uses a deep relative import for the new decorator
The plan shows:
import { NhrAdapterWithObservability } from '../observability/NhrAdapterWithObservability'
With the corrected placement (src/business/adapters/), the import from src/hooks/useDmpNhr.ts becomes:
import { NhrAdapterWithObservability } from '../business/adapters/NhrAdapterWithObservability'
That is a two-level traversal — acceptable without an alias. But this is only correct after applying the fix from issue #1. The plan's proposed path would be a two-level traversal too (../observability/), so neither triggers the 3+ level alias rule. Still, the path changes materially depending on the folder decision, so the plan needs a consistent final path.
8. propertyName deduplication uses a type assertion instead of a type-safe filter
In the decorator's updateDocumentMetadata:
const propertyNames = [...new Set(
payloads.map((p) => p.propertyName).filter(Boolean)
)] as string[]
NhrDocumentMetadataUpdatePayload.propertyName is typed string | undefined. The .filter(Boolean) call does not narrow the type in TypeScript without help, hence the as string[] cast. This should use a type guard instead:
const propertyNames = [
...new Set(payloads.map((p) => p.propertyName).filter((n): n is string => n !== undefined))
]
This avoids an unsafe cast and is consistent with the project's TypeScript rules (no suppression of errors via casts).
Suggestions (consider improving)
9. adapter field typed as string — consider a string literal union
The adapter field on both NhrRequestDetails and NhrResponseDetails is typed as string. The plan already enumerates the intended values ('dmp', 'germany-kim', 'italy-fse'). Typing it as string provides no compile-time safety. A const union type or at minimum a named alias would make future adapters self-documenting:
export type NhrAdapterName = 'dmp' // extend when new adapters are added
type NhrRequestDetails = {
// ...
adapter: NhrAdapterName
// ...
}
10. NhrAdapterWithObservability constructor takes adapterName: string — couple this to the type from suggestion #9
If NhrAdapterName is introduced, the constructor signature becomes:
constructor(adapter: NhrAdapter, adapterName: NhrAdapterName)
This ensures incorrect adapter names are caught at the call site in useDmpNhr.ts at compile time.
11. getDocumentsContent does not send requested_count on the request event
For searchDocuments and updateDocumentMetadata, the request event carries contextual metadata (filter counts, payloads count). For getDocumentsContent, the request event carries no metadata at all. This is inconsistent: props.params.ids.length is already available at request time and is safe to include (it's a count, not the IDs themselves). Adding requested_count to the request event would enable detecting operations that request N documents and never receive a response.
12. The plan does not address DmpNhrAdapter being exported publicly from src/index.ts
DmpNhrAdapter is currently exported directly from the package entrypoint. With the decorator in place, consumers constr
…(truncated, 319 more chars)