Source Code

;; title: HealthAI
;; version:
;; summary:
;; description:

(define-trait healthcare-product-tracking-trait (
  (onboard-product
    (uint uint)
    (response bool uint)
  )
  (modify-product-phase
    (uint uint)
    (response bool uint)
  )
  (retrieve-product-timeline
    (uint)
    (
      response       (list 10 {
      phase: uint,
      moment: uint,
    })
      uint
    )
  )
  (attach-validation
    (uint uint principal)
    (response bool uint)
  )
  (confirm-validation
    (uint uint)
    (response bool uint)
  )
))

;; traits
;;
;; Define product phase constants
(define-constant PHASE_PRODUCED u1)
(define-constant PHASE_EVALUATION u2)
(define-constant PHASE_ACTIVE u3)
(define-constant PHASE_SERVICED u4)

;; token definitions
;;
;; Define validation type constants
(define-constant VALIDATION_TYPE_HEALTH_ADMIN u1)
(define-constant VALIDATION_TYPE_EUROPEAN u2)
(define-constant VALIDATION_TYPE_QUALITY u3)
(define-constant VALIDATION_TYPE_SECURITY u4)

;; constants
;;
;; Error constants
(define-constant ERR_NO_PERMISSION (err u1))
(define-constant ERR_PRODUCT_NOT_FOUND (err u2))
(define-constant ERR_PHASE_UPDATE_FAILED (err u3))
(define-constant ERR_INVALID_PHASE (err u4))
(define-constant ERR_INVALID_VALIDATION (err u5))

(define-constant ERR_VALIDATION_ALREADY_EXISTS (err u6))

;; data vars
;;
;; Contract administrator
(define-data-var admin-address principal tx-sender)

;; data maps
;;
;; Current moment counter
(define-data-var moment-counter uint u0)

;; public functions
;;
;; Product tracking map
(define-map product-data
  { product-id: uint }
  {
    creator: principal,
    current-phase: uint,
    timeline: (list 10 {
      phase: uint,
      moment: uint,
    }),
  }
)

;; read only functions
;;
;; Validation tracking map
(define-map product-validations
  {
    product-id: uint,
    validation-type: uint,
  }
  {
    validator: principal,
    moment: uint,
    active: bool,
  }
)

;; private functions
;;
;; Approved oversight entities
(define-map oversight-entities
  {
    entity: principal,
    validation-type: uint,
  }
  { authorized: bool }
)

;;;;  Only admin can perform certain actions
(define-read-only (is-admin (caller principal))
  (is-eq caller (var-get admin-address))
)

;; Get product timeline
(define-read-only (retrieve-product-timeline (product-id uint))
  (let ((product (unwrap! (map-get? product-data { product-id: product-id })
      ERR_PRODUCT_NOT_FOUND
    )))
    (ok (get timeline product))
  )
)

;; Get current product phase
(define-read-only (get-product-phase (product-id uint))
  (let ((product (unwrap! (map-get? product-data { product-id: product-id })
      ERR_PRODUCT_NOT_FOUND
    )))
    (ok (get current-phase product))
  )
)

;; Verify product validation
(define-read-only (confirm-validation
    (product-id uint)
    (validation-type uint)
  )
  (let ((validation (unwrap!
      (map-get? product-validations {
        product-id: product-id,
        validation-type: validation-type,
      })
      ERR_INVALID_VALIDATION
    )))
    (ok (get active validation))
  )
)

;; Get validation details
(define-read-only (get-validation-details
    (product-id uint)
    (validation-type uint)
  )
  (ok (map-get? product-validations {
    product-id: product-id,
    validation-type: validation-type,
  }))
)

;; Validate phase
(define-private (is-valid-phase (phase uint))
  (or
    (is-eq phase PHASE_PRODUCED)
    (is-eq phase PHASE_EVALUATION)
    (is-eq phase PHASE_ACTIVE)
    (is-eq phase PHASE_SERVICED)
  )
)

;; Get current moment and increment counter
(define-private (get-current-moment)
  (begin
    (var-set moment-counter (+ (var-get moment-counter) u1))
    (var-get moment-counter)
  )
)

;; Validate validation type
(define-private (is-valid-validation-type (validation-type uint))
  (or
    (is-eq validation-type VALIDATION_TYPE_HEALTH_ADMIN)
    (is-eq validation-type VALIDATION_TYPE_EUROPEAN)
    (is-eq validation-type VALIDATION_TYPE_QUALITY)
    (is-eq validation-type VALIDATION_TYPE_SECURITY)
  )
)

;; Validate product ID
(define-private (is-valid-product-id (product-id uint))
  (and (> product-id u0) (<= product-id u1000000))
)

;; Validate entity principal
(define-private (is-valid-entity (entity principal))
  (and
    (not (is-eq entity (var-get admin-address))) ;; Entity can't be contract admin
    (not (is-eq entity tx-sender)) ;; Entity can't be the sender
    (not (is-eq entity 'SP000000000000000000002Q6VF78)) ;; Not zero address
  )
)

;; Check if sender is approved oversight entity
(define-private (is-oversight-entity
    (entity principal)
    (validation-type uint)
  )
  (default-to false
    (get authorized
      (map-get? oversight-entities {
        entity: entity,
        validation-type: validation-type,
      })
    ))
)

;;;;;;;;; PUBLIC FUNCTION ;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 

;; Register a new product
(define-public (onboard-product
    (product-id uint)
    (initial-phase uint)
  )
  (begin
    (asserts! (is-valid-product-id product-id) ERR_PRODUCT_NOT_FOUND)
    (asserts! (is-valid-phase initial-phase) ERR_INVALID_PHASE)
    (asserts! (or (is-admin tx-sender) (is-eq initial-phase PHASE_PRODUCED))
      ERR_NO_PERMISSION
    )

    (map-set product-data { product-id: product-id } {
      creator: tx-sender,
      current-phase: initial-phase,
      timeline: (list {
        phase: initial-phase,
        moment: (get-current-moment),
      }),
    })
    (ok true)
  )
)

;; Update product phase
(define-public (modify-product-phase
    (product-id uint)
    (new-phase uint)
  )
  (let ((product (unwrap! (map-get? product-data { product-id: product-id })
      ERR_PRODUCT_NOT_FOUND
    )))
    (asserts! (is-valid-product-id product-id) ERR_PRODUCT_NOT_FOUND)
    (asserts! (is-valid-phase new-phase) ERR_INVALID_PHASE)
    (asserts!
      (or
        (is-admin tx-sender)
        (is-eq (get creator product) tx-sender)
      )
      ERR_NO_PERMISSION
    )

    (map-set product-data { product-id: product-id }
      (merge product {
        current-phase: new-phase,
        timeline: (unwrap-panic (as-max-len?
          (append (get timeline product) {
            phase: new-phase,
            moment: (get-current-moment),
          })
          u10
        )),
      })
    )
    (ok true)
  )
)

;; Add oversight entity with additional validation
(define-public (add-oversight-entity
    (entity principal)
    (validation-type uint)
  )
  (begin
    (asserts! (is-admin tx-sender) ERR_NO_PERMISSION)
    (asserts! (is-valid-validation-type validation-type) ERR_INVALID_VALIDATION)
    (asserts! (is-valid-entity entity) ERR_NO_PERMISSION)

    ;; After validation, we can safely use the entity
    (map-set oversight-entities {
      entity: entity,
      validation-type: validation-type,
    } { authorized: true }
    )
    (ok true)
  )
)

;; Add validation to product
(define-public (attach-validation
    (product-id uint)
    (validation-type uint)
  )
  (begin
    (asserts! (is-valid-product-id product-id) ERR_PRODUCT_NOT_FOUND)
    (asserts! (is-valid-validation-type validation-type) ERR_INVALID_VALIDATION)
    (asserts! (is-oversight-entity tx-sender validation-type) ERR_NO_PERMISSION)

    (asserts!
      (is-none (map-get? product-validations {
        product-id: product-id,
        validation-type: validation-type,
      }))
      ERR_VALIDATION_ALREADY_EXISTS
    )

    (let (
        (validated-product-id product-id)
        (validated-validation-type validation-type)
      )
      (map-set product-validations {
        product-id: validated-product-id,
        validation-type: validated-validation-type,
      } {
        validator: tx-sender,
        moment: (get-current-moment),
        active: true,
      })
      (ok true)
    )
  )
)

;; Revoke validation
(define-public (withdraw-validation
    (product-id uint)
    (validation-type uint)
  )
  (begin
    (asserts! (is-valid-product-id product-id) ERR_PRODUCT_NOT_FOUND)
    (asserts! (is-valid-validation-type validation-type) ERR_INVALID_VALIDATION)

    (let (
        (validation (unwrap!
          (map-get? product-validations {
            product-id: product-id,
            validation-type: validation-type,
          })
          ERR_INVALID_VALIDATION
        ))
        (validated-product-id product-id)
        (validated-validation-type validation-type)
      )
      (asserts!
        (or
          (is-admin tx-sender)
          (is-eq (get validator validation) tx-sender)
        )
        ERR_NO_PERMISSION
      )

      (map-set product-validations {
        product-id: validated-product-id,
        validation-type: validated-validation-type,
      }
        (merge validation { active: false })
      )
      (ok true)
    )
  )
)

Functions (8)

FunctionAccessArgs
is-adminread-onlycaller: principal
retrieve-product-timelineread-onlyproduct-id: uint
get-product-phaseread-onlyproduct-id: uint
is-valid-phaseprivatephase: uint
get-current-momentprivate
is-valid-validation-typeprivatevalidation-type: uint
is-valid-product-idprivateproduct-id: uint
is-valid-entityprivateentity: principal