Source Code

;; fhir-adapter - Clarity 4
;; FHIR (Fast Healthcare Interoperability Resources) standard adapter

(define-constant ERR-NOT-AUTHORIZED (err u100))
(define-constant ERR-RESOURCE-NOT-FOUND (err u101))
(define-constant ERR-INVALID-FORMAT (err u102))
(define-constant ERR-VERSION-MISMATCH (err u103))

(define-map fhir-resources uint
  {
    resource-type: (string-ascii 50),
    resource-id: (string-ascii 100),
    fhir-version: (string-ascii 10),
    resource-hash: (buff 64),
    owner: principal,
    created-at: uint,
    last-updated: uint,
    is-active: bool
  }
)

(define-map resource-mappings { source-system: (string-ascii 50), external-id: (string-ascii 100) }
  {
    internal-resource-id: uint,
    mapping-version: uint,
    mapped-at: uint,
    is-verified: bool
  }
)

(define-map fhir-extensions uint
  {
    resource-id: uint,
    extension-url: (string-utf8 256),
    extension-value-hash: (buff 64),
    extension-type: (string-ascii 50)
  }
)

(define-map validation-results uint
  {
    resource-id: uint,
    validator: principal,
    is-valid: bool,
    validation-errors: (list 10 (string-ascii 100)),
    validated-at: uint
  }
)

(define-data-var resource-counter uint u0)
(define-data-var extension-counter uint u0)
(define-data-var validation-counter uint u0)
(define-data-var supported-version (string-ascii 10) "R4")

(define-public (register-fhir-resource
    (resource-type (string-ascii 50))
    (resource-id (string-ascii 100))
    (fhir-version (string-ascii 10))
    (resource-hash (buff 64)))
  (let ((internal-id (+ (var-get resource-counter) u1)))
    (asserts! (is-eq fhir-version (var-get supported-version)) ERR-VERSION-MISMATCH)
    (map-set fhir-resources internal-id
      {
        resource-type: resource-type,
        resource-id: resource-id,
        fhir-version: fhir-version,
        resource-hash: resource-hash,
        owner: tx-sender,
        created-at: stacks-block-time,
        last-updated: stacks-block-time,
        is-active: true
      })
    (var-set resource-counter internal-id)
    (ok internal-id)))

(define-public (create-resource-mapping
    (source-system (string-ascii 50))
    (external-id (string-ascii 100))
    (internal-resource-id uint)
    (mapping-version uint))
  (let ((resource (unwrap! (map-get? fhir-resources internal-resource-id) ERR-RESOURCE-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get owner resource)) ERR-NOT-AUTHORIZED)
    (ok (map-set resource-mappings { source-system: source-system, external-id: external-id }
      {
        internal-resource-id: internal-resource-id,
        mapping-version: mapping-version,
        mapped-at: stacks-block-time,
        is-verified: false
      }))))

(define-public (add-extension
    (resource-id uint)
    (extension-url (string-utf8 256))
    (extension-value-hash (buff 64))
    (extension-type (string-ascii 50)))
  (let ((resource (unwrap! (map-get? fhir-resources resource-id) ERR-RESOURCE-NOT-FOUND))
        (extension-id (+ (var-get extension-counter) u1)))
    (asserts! (is-eq tx-sender (get owner resource)) ERR-NOT-AUTHORIZED)
    (map-set fhir-extensions extension-id
      {
        resource-id: resource-id,
        extension-url: extension-url,
        extension-value-hash: extension-value-hash,
        extension-type: extension-type
      })
    (var-set extension-counter extension-id)
    (ok extension-id)))

(define-public (validate-resource
    (resource-id uint)
    (is-valid bool)
    (errors (list 10 (string-ascii 100))))
  (let ((validation-id (+ (var-get validation-counter) u1)))
    (map-set validation-results validation-id
      {
        resource-id: resource-id,
        validator: tx-sender,
        is-valid: is-valid,
        validation-errors: errors,
        validated-at: stacks-block-time
      })
    (var-set validation-counter validation-id)
    (ok validation-id)))

(define-public (update-resource
    (resource-id uint)
    (new-hash (buff 64)))
  (let ((resource (unwrap! (map-get? fhir-resources resource-id) ERR-RESOURCE-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get owner resource)) ERR-NOT-AUTHORIZED)
    (ok (map-set fhir-resources resource-id
      (merge resource {
        resource-hash: new-hash,
        last-updated: stacks-block-time
      })))))

(define-public (verify-mapping
    (source-system (string-ascii 50))
    (external-id (string-ascii 100)))
  (let ((mapping (unwrap! (map-get? resource-mappings { source-system: source-system, external-id: external-id }) ERR-RESOURCE-NOT-FOUND)))
    (ok (map-set resource-mappings { source-system: source-system, external-id: external-id }
      (merge mapping { is-verified: true })))))

(define-read-only (get-fhir-resource (resource-id uint))
  (ok (map-get? fhir-resources resource-id)))

(define-read-only (get-resource-mapping (source-system (string-ascii 50)) (external-id (string-ascii 100)))
  (ok (map-get? resource-mappings { source-system: source-system, external-id: external-id })))

(define-read-only (get-extension (extension-id uint))
  (ok (map-get? fhir-extensions extension-id)))

(define-read-only (get-validation-result (validation-id uint))
  (ok (map-get? validation-results validation-id)))

(define-read-only (validate-principal (p principal))
  (principal-destruct? p))

(define-read-only (format-resource-id (resource-id uint))
  (ok (int-to-ascii resource-id)))

(define-read-only (parse-resource-id (id-str (string-ascii 20)))
  (string-to-uint? id-str))

(define-read-only (get-bitcoin-block)
  (ok burn-block-height))

Functions (14)

FunctionAccessArgs
register-fhir-resourcepublicresource-type: (string-ascii 50
create-resource-mappingpublicsource-system: (string-ascii 50
add-extensionpublicresource-id: uint, extension-url: (string-utf8 256
validate-resourcepublicresource-id: uint, is-valid: bool, errors: (list 10 (string-ascii 100
update-resourcepublicresource-id: uint, new-hash: (buff 64
verify-mappingpublicsource-system: (string-ascii 50
get-fhir-resourceread-onlyresource-id: uint
get-resource-mappingread-onlysource-system: (string-ascii 50
get-extensionread-onlyextension-id: uint
get-validation-resultread-onlyvalidation-id: uint
validate-principalread-onlyp: principal
format-resource-idread-onlyresource-id: uint
parse-resource-idread-onlyid-str: (string-ascii 20
get-bitcoin-blockread-only