;; 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))