code wiki / (root) / nx_haccp.nx

nx_haccp.nx source

↩ module page · 146 lines · 5507 B

1// nx_haccp.nx -- FOOD-SCIENCE SUITE / REGULATORY (HACCP) rung. Turns the 2// safety + preservation science into the HACCP framework: for each process 3// step it names the hazard, decides whether the step is a CRITICAL CONTROL 4// POINT (CCP) or a prerequisite (PRP), sets the grounded CRITICAL LIMIT, 5// monitors an observation against it, and HALTS the batch when a CCP is 6// breached (the never-poison law applied to a whole process). 7// 8// Grounded critical limits (FDA Food Code 2022): 9// cook poultry 74 C (165 F) / ground 71 / whole cut + seafood 63 10// reheat 74 C; hot-hold >= 57 C (135 F); cold-hold <= 5 C (41 F) 11// two-stage cooling 57->21 C in <= 2 h, then 21->5 C in <= 4 h 12// low-acid canning: 12-D botulinum cook (composes nx_preservation) 13// acidification: pH <= 4.6 (composes the ferment never-poison line) 14// 15// THE exceed: a paper HACCP binder lists limits; this MONITORS an 16// observation against the grounded limit and HALTS by construction when a 17// CCP fails -- and it reuses the SAME preservation/ferment science the rest 18// of the suite runs on (one source of truth, not a re-typed chart). 19// 20// genealogy_id: codex_haccp_7_principles + fda_food_code_2022 + nishi_never_poison 21 22import "nx_syscalls.nx" 23import "nx_preservation.nx" 24 25// ===== Sealed enums =============================================== 26 27const HC_RECEIVE: i64 = 0 28const HC_STORE: i64 = 1 29const HC_PREP: i64 = 2 30const HC_COOK: i64 = 3 31const HC_COOL: i64 = 4 32const HC_HOT_HOLD: i64 = 5 33const HC_COLD_HOLD: i64 = 6 34const HC_REHEAT: i64 = 7 35const HC_CAN: i64 = 8 36const HC_ACIDIFY: i64 = 9 37const HC_SERVE: i64 = 10 38const HC_STEP_N: i64 = 11 39 40const HC_HAZ_NONE: i64 = 0 41const HC_HAZ_BIO: i64 = 1 // pathogens 42const HC_HAZ_CHEM: i64 = 2 // allergens, toxins, residues 43const HC_HAZ_PHYS: i64 = 3 // glass, metal, bone 44 45const HC_CCP_NO: i64 = 0 // prerequisite program (PRP) 46const HC_CCP_YES: i64 = 1 // critical control point 47 48const HC_OK: i64 = 0 49const HC_HALT: i64 = 1 // CCP breached -> never-poison halt 50 51// Food classes for cook limits. 52const HC_FOOD_POULTRY: i64 = 0 53const HC_FOOD_GROUND: i64 = 1 54const HC_FOOD_WHOLE: i64 = 2 55const HC_FOOD_SEAFOOD: i64 = 3 56 57// ===== Grounded critical limits =================================== 58 59const HC_COOK_POULTRY_C: i64 = 74 60const HC_COOK_GROUND_C: i64 = 71 61const HC_COOK_WHOLE_C: i64 = 63 62const HC_REHEAT_C: i64 = 74 63const HC_HOT_HOLD_C: i64 = 57 64const HC_COLD_HOLD_C: i64 = 5 65const HC_COOL_S1_HOURS: i64 = 2 // 57 C -> 21 C within 2 h 66const HC_COOL_S2_HOURS: i64 = 4 // 21 C -> 5 C within 4 h 67const HC_ACIDIFY_PH: i64 = 4600 68 69// ===== Hazard analysis + CCP determination ======================== 70 71func haccp_primary_hazard(step: i64) -> i64 { 72 if step == HC_RECEIVE { return HC_HAZ_BIO } 73 if step == HC_STORE { return HC_HAZ_BIO } 74 if step == HC_PREP { return HC_HAZ_PHYS } 75 if step == HC_COOK { return HC_HAZ_BIO } 76 if step == HC_COOL { return HC_HAZ_BIO } 77 if step == HC_HOT_HOLD { return HC_HAZ_BIO } 78 if step == HC_COLD_HOLD { return HC_HAZ_BIO } 79 if step == HC_REHEAT { return HC_HAZ_BIO } 80 if step == HC_CAN { return HC_HAZ_BIO } 81 if step == HC_ACIDIFY { return HC_HAZ_BIO } 82 return HC_HAZ_NONE 83} 84 85// A step is a CCP iff a significant hazard is controlled there (cook/cool/ 86// hold/reheat/can/acidify); receive/store/prep/serve are prerequisites. 87func haccp_is_ccp(step: i64) -> i64 { 88 if step == HC_COOK { return HC_CCP_YES } 89 if step == HC_COOL { return HC_CCP_YES } 90 if step == HC_HOT_HOLD { return HC_CCP_YES } 91 if step == HC_COLD_HOLD { return HC_CCP_YES } 92 if step == HC_REHEAT { return HC_CCP_YES } 93 if step == HC_CAN { return HC_CCP_YES } 94 if step == HC_ACIDIFY { return HC_CCP_YES } 95 return HC_CCP_NO 96} 97 98// ===== Critical limits + monitoring =============================== 99 100func haccp_cook_limit(food_class: i64) -> i64 { 101 if food_class == HC_FOOD_POULTRY { return HC_COOK_POULTRY_C } 102 if food_class == HC_FOOD_GROUND { return HC_COOK_GROUND_C } 103 if food_class == HC_FOOD_WHOLE { return HC_COOK_WHOLE_C } 104 if food_class == HC_FOOD_SEAFOOD { return HC_COOK_WHOLE_C } 105 return HC_COOK_POULTRY_C // fail-safe: highest limit for unknown 106} 107 108// COOK CCP: observed internal temp must reach the class limit. 109func haccp_cook_admit(observed_c: i64, food_class: i64) -> i64 { 110 if observed_c >= haccp_cook_limit(food_class) { return HC_OK } 111 return HC_HALT 112} 113 114// COOL CCP: two-stage cooling (each stage within its hour limit). 115func haccp_cool_admit(stage1_hours: i64, stage2_hours: i64) -> i64 { 116 if stage1_hours > HC_COOL_S1_HOURS { return HC_HALT } 117 if stage2_hours > HC_COOL_S2_HOURS { return HC_HALT } 118 return HC_OK 119} 120 121func haccp_hot_hold_admit(observed_c: i64) -> i64 { 122 if observed_c >= HC_HOT_HOLD_C { return HC_OK } 123 return HC_HALT 124} 125 126func haccp_cold_hold_admit(observed_c: i64) -> i64 { 127 if observed_c <= HC_COLD_HOLD_C { return HC_OK } 128 return HC_HALT 129} 130 131func haccp_reheat_admit(observed_c: i64) -> i64 { 132 if observed_c >= HC_REHEAT_C { return HC_OK } 133 return HC_HALT 134} 135 136// CAN CCP: reuse the preservation 12-D botulinum cook (one source of truth). 137func haccp_can_admit(hold_mmin: i64, d_mmin: i64) -> i64 { 138 if pv_is_12d(hold_mmin, d_mmin) == 1 { return HC_OK } 139 return HC_HALT 140} 141 142// ACIDIFY CCP: pH must reach the botulinum line. 143func haccp_acidify_admit(ph_milli: i64) -> i64 { 144 if ph_milli <= HC_ACIDIFY_PH { return HC_OK } 145 return HC_HALT 146}