Source Code

;; hipaa-compliance - Clarity 4
;; HIPAA compliance verification and enforcement

(define-constant ERR-NOT-AUTHORIZED (err u100))
(define-constant ERR-ENTITY-NOT-FOUND (err u101))
(define-constant ERR-VIOLATION-DETECTED (err u102))
(define-constant ERR-AUDIT-FAILED (err u103))

(define-map covered-entities principal
  {
    entity-name: (string-utf8 200),
    entity-type: (string-ascii 50),
    registration-date: uint,
    compliance-officer: principal,
    is-compliant: bool,
    last-audit: uint
  }
)

(define-map phi-access-logs uint
  {
    entity: principal,
    accessor: principal,
    patient-id: (string-ascii 50),
    access-type: (string-ascii 50),
    purpose: (string-utf8 200),
    timestamp: uint,
    compliant: bool
  }
)

(define-map breach-reports uint
  {
    reporting-entity: principal,
    breach-type: (string-ascii 100),
    affected-records: uint,
    reported-at: uint,
    resolution-status: (string-ascii 20),
    investigation-hash: (buff 64)
  }
)

(define-map business-associate-agreements { entity: principal, associate: principal }
  {
    agreement-hash: (buff 64),
    effective-date: uint,
    expiration-date: uint,
    is-active: bool
  }
)

(define-map patient-rights-requests uint
  {
    patient: principal,
    request-type: (string-ascii 50),
    entity: principal,
    requested-at: uint,
    fulfilled: bool,
    fulfilled-at: (optional uint)
  }
)

(define-data-var access-log-counter uint u0)
(define-data-var breach-counter uint u0)
(define-data-var rights-request-counter uint u0)

;; Register covered entity
(define-public (register-covered-entity
    (entity-name (string-utf8 200))
    (entity-type (string-ascii 50))
    (compliance-officer principal))
  (ok (map-set covered-entities tx-sender
    {
      entity-name: entity-name,
      entity-type: entity-type,
      registration-date: stacks-block-time,
      compliance-officer: compliance-officer,
      is-compliant: true,
      last-audit: stacks-block-time
    })))

;; Log PHI access
(define-public (log-phi-access
    (patient-id (string-ascii 50))
    (access-type (string-ascii 50))
    (purpose (string-utf8 200)))
  (let ((log-id (+ (var-get access-log-counter) u1)))
    (map-set phi-access-logs log-id
      {
        entity: tx-sender,
        accessor: tx-sender,
        patient-id: patient-id,
        access-type: access-type,
        purpose: purpose,
        timestamp: stacks-block-time,
        compliant: true
      })
    (var-set access-log-counter log-id)
    (ok log-id)))

;; Report breach
(define-public (report-breach
    (breach-type (string-ascii 100))
    (affected-records uint)
    (investigation-hash (buff 64)))
  (let ((breach-id (+ (var-get breach-counter) u1)))
    (map-set breach-reports breach-id
      {
        reporting-entity: tx-sender,
        breach-type: breach-type,
        affected-records: affected-records,
        reported-at: stacks-block-time,
        resolution-status: "investigating",
        investigation-hash: investigation-hash
      })
    (try! (update-compliance-status tx-sender false))
    (var-set breach-counter breach-id)
    (ok breach-id)))

;; Execute business associate agreement
(define-public (execute-baa
    (associate principal)
    (agreement-hash (buff 64))
    (duration uint))
  (ok (map-set business-associate-agreements { entity: tx-sender, associate: associate }
    {
      agreement-hash: agreement-hash,
      effective-date: stacks-block-time,
      expiration-date: (+ stacks-block-time duration),
      is-active: true
    })))

;; Submit patient rights request
(define-public (submit-rights-request
    (request-type (string-ascii 50))
    (entity principal))
  (let ((request-id (+ (var-get rights-request-counter) u1)))
    (map-set patient-rights-requests request-id
      {
        patient: tx-sender,
        request-type: request-type,
        entity: entity,
        requested-at: stacks-block-time,
        fulfilled: false,
        fulfilled-at: none
      })
    (var-set rights-request-counter request-id)
    (ok request-id)))

;; Fulfill rights request
(define-public (fulfill-rights-request (request-id uint))
  (let ((request (unwrap! (map-get? patient-rights-requests request-id) ERR-ENTITY-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get entity request)) ERR-NOT-AUTHORIZED)
    (ok (map-set patient-rights-requests request-id
      (merge request { fulfilled: true, fulfilled-at: (some stacks-block-time) })))))

;; Update breach resolution
(define-public (update-breach-status (breach-id uint) (new-status (string-ascii 20)))
  (let ((breach (unwrap! (map-get? breach-reports breach-id) ERR-ENTITY-NOT-FOUND)))
    (asserts! (is-eq tx-sender (get reporting-entity breach)) ERR-NOT-AUTHORIZED)
    (ok (map-set breach-reports breach-id
      (merge breach { resolution-status: new-status })))))

;; Update compliance status
(define-private (update-compliance-status (entity principal) (compliant bool))
  (let ((entity-info (unwrap! (map-get? covered-entities entity) ERR-ENTITY-NOT-FOUND)))
    (map-set covered-entities entity
      (merge entity-info { is-compliant: compliant, last-audit: stacks-block-time }))
    (ok true)))

;; Conduct compliance audit
(define-public (conduct-audit (entity principal))
  (let ((entity-info (unwrap! (map-get? covered-entities entity) ERR-ENTITY-NOT-FOUND)))
    (ok (map-set covered-entities entity
      (merge entity-info { last-audit: stacks-block-time })))))

;; Read-only functions
(define-read-only (get-entity-info (entity principal))
  (ok (map-get? covered-entities entity)))

(define-read-only (get-access-log (log-id uint))
  (ok (map-get? phi-access-logs log-id)))

(define-read-only (get-breach-report (breach-id uint))
  (ok (map-get? breach-reports breach-id)))

(define-read-only (get-baa (entity principal) (associate principal))
  (ok (map-get? business-associate-agreements { entity: entity, associate: associate })))

(define-read-only (get-rights-request (request-id uint))
  (ok (map-get? patient-rights-requests request-id)))

(define-read-only (is-entity-compliant (entity principal))
  (match (map-get? covered-entities entity)
    info (ok (get is-compliant info))
    (ok false)))

;; Clarity 4: principal-destruct?
(define-read-only (validate-entity (entity principal))
  (principal-destruct? entity))

;; Clarity 4: int-to-ascii
(define-read-only (format-log-id (log-id uint))
  (ok (int-to-ascii log-id)))

;; Clarity 4: string-to-uint?
(define-read-only (parse-log-id (id-str (string-ascii 20)))
  (string-to-uint? id-str))

;; Clarity 4: burn-block-height
(define-read-only (get-bitcoin-block)
  (ok burn-block-height))

Functions (19)

FunctionAccessArgs
register-covered-entitypublicentity-name: (string-utf8 200
log-phi-accesspublicpatient-id: (string-ascii 50
report-breachpublicbreach-type: (string-ascii 100
execute-baapublicassociate: principal, agreement-hash: (buff 64
submit-rights-requestpublicrequest-type: (string-ascii 50
fulfill-rights-requestpublicrequest-id: uint
update-breach-statuspublicbreach-id: uint, new-status: (string-ascii 20
update-compliance-statusprivateentity: principal, compliant: bool
conduct-auditpublicentity: principal
get-entity-inforead-onlyentity: principal
get-access-logread-onlylog-id: uint
get-breach-reportread-onlybreach-id: uint
get-baaread-onlyentity: principal, associate: principal
get-rights-requestread-onlyrequest-id: uint
is-entity-compliantread-onlyentity: principal
validate-entityread-onlyentity: principal
format-log-idread-onlylog-id: uint
parse-log-idread-onlyid-str: (string-ascii 20
get-bitcoin-blockread-only