mirror of
https://github.com/temetro/temetro.git
synced 2026-08-11 02:57:55 +00:00
0d2494d67a
Expose temetro's own records as a read-only FHIR R4 server at /fhir, authenticated with per-clinic API keys (tmf_… bearer tokens, SHA-256 hashed, shown once). Serves Patient, Observation (labs + vitals), AllergyIntolerance, Condition, MedicationRequest, Encounter and Appointment as text-only CodeableConcepts (temetro stores free-text clinical values); CapabilityStatement at /fhir/metadata (unauth). Searchset Bundles with _count/_offset pagination and self/next/prev links; every request is org-scoped and written to the activity log. Keys are created/revoked under Settings → Integrations (owner/admin). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
115 lines
3.4 KiB
TypeScript
115 lines
3.4 KiB
TypeScript
// A static CapabilityStatement describing exactly what this read-only FHIR R4
|
|
// server supports. It is intentionally honest: only the resources and search
|
|
// params implemented below are listed, everything is `read`/`search-type` only,
|
|
// and clinical concepts are text-only (no SNOMED/LOINC coding).
|
|
|
|
type ResourceCapability = {
|
|
type: string;
|
|
interaction: { code: "read" | "search-type" }[];
|
|
searchParam?: { name: string; type: "token" | "string" | "reference" }[];
|
|
};
|
|
|
|
const RESOURCES: ResourceCapability[] = [
|
|
{
|
|
type: "Patient",
|
|
interaction: [{ code: "read" }, { code: "search-type" }],
|
|
searchParam: [
|
|
{ name: "identifier", type: "token" },
|
|
{ name: "name", type: "string" },
|
|
],
|
|
},
|
|
{
|
|
type: "Observation",
|
|
interaction: [{ code: "read" }, { code: "search-type" }],
|
|
searchParam: [
|
|
{ name: "patient", type: "reference" },
|
|
{ name: "patient.identifier", type: "token" },
|
|
{ name: "category", type: "token" },
|
|
],
|
|
},
|
|
{
|
|
type: "AllergyIntolerance",
|
|
interaction: [{ code: "read" }, { code: "search-type" }],
|
|
searchParam: [
|
|
{ name: "patient", type: "reference" },
|
|
{ name: "patient.identifier", type: "token" },
|
|
],
|
|
},
|
|
{
|
|
type: "Condition",
|
|
interaction: [{ code: "read" }, { code: "search-type" }],
|
|
searchParam: [
|
|
{ name: "patient", type: "reference" },
|
|
{ name: "patient.identifier", type: "token" },
|
|
],
|
|
},
|
|
{
|
|
type: "MedicationRequest",
|
|
interaction: [{ code: "read" }, { code: "search-type" }],
|
|
searchParam: [
|
|
{ name: "patient", type: "reference" },
|
|
{ name: "patient.identifier", type: "token" },
|
|
],
|
|
},
|
|
{
|
|
type: "Encounter",
|
|
interaction: [{ code: "read" }, { code: "search-type" }],
|
|
searchParam: [
|
|
{ name: "patient", type: "reference" },
|
|
{ name: "patient.identifier", type: "token" },
|
|
],
|
|
},
|
|
{
|
|
type: "Appointment",
|
|
interaction: [{ code: "read" }, { code: "search-type" }],
|
|
searchParam: [
|
|
{ name: "patient", type: "reference" },
|
|
{ name: "patient.identifier", type: "token" },
|
|
],
|
|
},
|
|
];
|
|
|
|
export function capabilityStatement(
|
|
baseUrl: string,
|
|
version: string,
|
|
): Record<string, unknown> {
|
|
return {
|
|
resourceType: "CapabilityStatement",
|
|
status: "active",
|
|
date: new Date().toISOString(),
|
|
publisher: "temetro",
|
|
kind: "instance",
|
|
implementation: { description: "temetro FHIR server", url: baseUrl },
|
|
software: { name: "temetro", version },
|
|
fhirVersion: "4.0.1",
|
|
format: ["application/fhir+json", "json"],
|
|
rest: [
|
|
{
|
|
mode: "server",
|
|
documentation:
|
|
"Read-only FHIR R4 server. Authenticate with a per-clinic API key: " +
|
|
"Authorization: Bearer tmf_…. Clinical values are text-only " +
|
|
"CodeableConcepts (no SNOMED/LOINC). Patients expose age (extension), " +
|
|
"not birthDate. Pagination via _count (default 50, max 200) and _offset.",
|
|
security: {
|
|
description: "Bearer token (per-organization API key, tmf_ prefix).",
|
|
service: [
|
|
{
|
|
coding: [
|
|
{
|
|
system:
|
|
"http://terminology.hl7.org/CodeSystem/restful-security-service",
|
|
code: "OAuth",
|
|
display: "OAuth",
|
|
},
|
|
],
|
|
text: "API key bearer token",
|
|
},
|
|
],
|
|
},
|
|
resource: RESOURCES,
|
|
},
|
|
],
|
|
};
|
|
}
|