nx_supp_jurisdiction.nx source
↩ module page · 248 lines · 9814 B
1// nx_supp_jurisdiction.nx -- SUPPLEMENT GTM SUITE / MARKET ACCESS rung.
2// Answers "where can this actually be manufactured and sold", per market,
3// with the premarket burden and the review clock made explicit.
4//
5// THE RESULT IS COUNTERINTUITIVE AND IT IS THE POINT OF THIS FILE. The
6// instinct when a market feels closed is to look offshore. For a BOTANICAL
7// or AMINO ACID supplement that instinct is backwards: the United States is
8// the most PERMISSIVE major market in the world, because DSHEA grandfathered
9// pre-1994 ingredients and requires NO premarket approval for them. Every
10// other market here demands premarket authorisation of some kind:
11//
12// US no approval for an old dietary ingredient; 75-day
13// notification only for a NEW one (least burden)
14// Australia listing against a permitted-ingredient list, fast
15// EAEU State Registration certificate (SGR) required BEFORE sale
16// Japan Foods with Function Claims, notify 60 days ahead
17// Canada product licence + NPN before sale
18// EU Novel Food authorisation for anything without significant
19// pre-1997 EU consumption history (most burden)
20//
21// So "go somewhere friendlier" is a real strategy for many industries and a
22// losing one here. The honest reason a botanical stack is easy to sell in
23// the US is that the US barely gates it.
24//
25// THE ONE THING NO JURISDICTION OFFERS. A substance regulated as a MEDICINE
26// has no supplement pathway anywhere on this list -- not the US, not the
27// EAEU, not anywhere. Kisspeptin-10, BPC-157, oxytocin and bremelanotide
28// are medicines or unapproved new drugs in every one of these markets, so
29// sj_any_peptide_supplement_path() returns 0 by construction rather than by
30// promise. A government partnership does not convert a drug into a
31// supplement; it just moves which regulator objects.
32//
33// TIMELINES AND FEES ARE INDICATIVE PLANNING FIGURES, not quotes -- they
34// move with dossier quality, ingredient novelty, and local counsel.
35// sj_estimate_is_indicative() exists so nothing downstream presents them as
36// commitments. Sanctions, banking access and export controls are a SEPARATE
37// analysis this file does not attempt and must not be read as clearing.
38//
39// Grounding (cited; researcher-groundable):
40// dshea_1994_old_dietary_ingredient_no_premarket_approval
41// fda_new_dietary_ingredient_75_day_notification
42// eaeu_tr_cu_021_2011_food_safety_state_registration_bad
43// eu_regulation_2015_2283_novel_food_authorisation
44// health_canada_natural_health_products_regulations_npn
45// tga_listed_complementary_medicines_permitted_ingredients
46//
47// genealogy_id: supplement_gtm + nishi_food_science_suite
48
49import "nx_syscalls.nx"
50import "nx_supp_ingredient.nx"
51const SJ_MAGIC_200000: i64 = 200000
52const SJ_MAGIC_800000: i64 = 800000
53const SJ_MAGIC_1000000: i64 = 1000000
54const SJ_MAGIC_500000: i64 = 500000
55const SJ_MAGIC_35000000: i64 = 35000000
56
57// ===== Markets (sealed) ===============================================
58
59const SJ_US: i64 = 0
60const SJ_EAEU: i64 = 1 // Belarus, Russia, Kazakhstan, Armenia, Kyrgyzstan
61const SJ_EU: i64 = 2
62const SJ_CANADA: i64 = 3
63const SJ_AUSTRALIA: i64 = 4
64const SJ_JAPAN: i64 = 5
65const SJ_N: i64 = 6
66
67const SJ_INVALID: i64 = 0 - 1
68
69// ===== Pathways (sealed) ==============================================
70
71const SJ_PATH_NONE: i64 = 0 // no lawful supplement route
72const SJ_PATH_NO_PREMARKET: i64 = 1 // notify/register facility only
73const SJ_PATH_NOTIFICATION: i64 = 2 // file and wait a statutory clock
74const SJ_PATH_REGISTRATION: i64 = 3 // dossier + certificate before sale
75const SJ_PATH_AUTHORISATION: i64 = 4 // full pre-approval (novel food)
76const SJ_PATH_DRUG_ONLY: i64 = 5 // medicines route, not a supplement
77
78func sj_valid(j: i64) -> i64 {
79 if j < 0 { return 0 }
80 if j >= SJ_N { return 0 }
81 return 1
82}
83
84func sj_name(j: i64) -> *u8 {
85 if j == SJ_US { return "United States" as *u8 }
86 if j == SJ_EAEU { return "EAEU (incl. Belarus)" as *u8 }
87 if j == SJ_EU { return "European Union" as *u8 }
88 if j == SJ_CANADA { return "Canada" as *u8 }
89 if j == SJ_AUSTRALIA { return "Australia" as *u8 }
90 if j == SJ_JAPAN { return "Japan" as *u8 }
91 return "UNKNOWN" as *u8
92}
93
94func sj_regime(j: i64) -> *u8 {
95 if j == SJ_US { return "DSHEA 1994 dietary supplement" as *u8 }
96 if j == SJ_EAEU { return "TR CU 021/2011 BAD state registration" as *u8 }
97 if j == SJ_EU { return "Novel Food Reg (EU) 2015/2283" as *u8 }
98 if j == SJ_CANADA { return "Natural Health Products Regs (NPN)" as *u8 }
99 if j == SJ_AUSTRALIA { return "TGA listed complementary medicine" as *u8 }
100 if j == SJ_JAPAN { return "Foods with Function Claims" as *u8 }
101 return "UNKNOWN" as *u8
102}
103
104// ===== Pathway per ingredient class ===================================
105//
106// The class comes from nx_supp_ingredient, so the drug/not-dietary verdict
107// is single-sourced and cannot drift between markets.
108
109func sj_pathway(j: i64, ingredient: i64) -> i64 {
110 if sj_valid(j) != 1 { return SJ_PATH_NONE }
111 let c: i64 = si_class(ingredient)
112 // A medicine is a medicine everywhere. No market on this list converts it.
113 if c == SI_CLASS_DRUG { return SJ_PATH_DRUG_ONLY }
114 if c == SI_CLASS_NOT_DIETARY { return SJ_PATH_NONE }
115 if c == SI_CLASS_UNKNOWN { return SJ_PATH_NONE }
116 // Lawful dietary ingredient: the burden is what differs.
117 if j == SJ_US {
118 if c == SI_CLASS_ODI { return SJ_PATH_NO_PREMARKET }
119 return SJ_PATH_NOTIFICATION
120 }
121 if j == SJ_EAEU { return SJ_PATH_REGISTRATION }
122 if j == SJ_EU { return SJ_PATH_AUTHORISATION }
123 if j == SJ_CANADA { return SJ_PATH_REGISTRATION }
124 if j == SJ_AUSTRALIA { return SJ_PATH_REGISTRATION }
125 if j == SJ_JAPAN { return SJ_PATH_NOTIFICATION }
126 return SJ_PATH_NONE
127}
128
129func sj_premarket_required(j: i64, ingredient: i64) -> i64 {
130 let p: i64 = sj_pathway(j, ingredient)
131 if p == SJ_PATH_NO_PREMARKET { return 0 }
132 if p == SJ_PATH_NONE { return 0 }
133 if p == SJ_PATH_DRUG_ONLY { return 0 }
134 return 1
135}
136
137func sj_is_sellable(j: i64, ingredient: i64) -> i64 {
138 let p: i64 = sj_pathway(j, ingredient)
139 if p == SJ_PATH_NONE { return 0 }
140 if p == SJ_PATH_DRUG_ONLY { return 0 }
141 return 1
142}
143
144// ===== Indicative burden ==============================================
145
146// Typical elapsed days before first lawful sale, for a lawful ingredient.
147func sj_review_days(j: i64) -> i64 {
148 if j == SJ_US { return 0 }
149 if j == SJ_AUSTRALIA { return 30 }
150 if j == SJ_EAEU { return 60 }
151 if j == SJ_JAPAN { return 60 }
152 if j == SJ_CANADA { return 180 }
153 if j == SJ_EU { return 540 }
154 return SJ_INVALID
155}
156
157// Indicative dossier/registration cost per SKU, CENTS.
158func sj_dossier_cost_cents(j: i64) -> i64 {
159 if j == SJ_US { return 0 }
160 if j == SJ_AUSTRALIA { return SJ_MAGIC_200000 }
161 if j == SJ_EAEU { return SJ_MAGIC_800000 }
162 if j == SJ_JAPAN { return SJ_MAGIC_1000000 }
163 if j == SJ_CANADA { return SJ_MAGIC_500000 }
164 if j == SJ_EU { return SJ_MAGIC_35000000 }
165 return SJ_INVALID
166}
167
168func sj_estimate_is_indicative(j: i64) -> i64 {
169 return 1
170}
171
172// Sanctions, banking access and export control are NOT modelled here. Always
173// 1, so a caller cannot mistake a green pathway for a cleared transaction.
174func sj_requires_separate_sanctions_review(j: i64) -> i64 {
175 return 1
176}
177
178// ===== Cross-market answers ===========================================
179
180// The market with the lowest premarket burden for a given lawful ingredient,
181// measured by review clock. Ties go to the earlier id.
182func sj_lowest_burden_market(ingredient: i64) -> i64 {
183 var j: i64 = 0
184 var best: i64 = SJ_INVALID
185 var bestd: i64 = 0
186 while j < SJ_N {
187 let ok: i64 = sj_is_sellable(j, ingredient)
188 if ok == 1 {
189 let d: i64 = sj_review_days(j)
190 if d >= 0 {
191 if best == SJ_INVALID { best = j; bestd = d }
192 if d < bestd { best = j; bestd = d }
193 }
194 }
195 j = j + 1
196 }
197 return best
198}
199
200// How many of the modelled markets will take this ingredient at all.
201func sj_markets_open(ingredient: i64) -> i64 {
202 var j: i64 = 0
203 var n: i64 = 0
204 while j < SJ_N {
205 let ok: i64 = sj_is_sellable(j, ingredient)
206 n = n + ok
207 j = j + 1
208 }
209 return n
210}
211
212// Does ANY modelled market offer a supplement route for a drug-class or
213// research-peptide substance? Computed across every market, not asserted --
214// so if a future market were added with a different answer, this would say so.
215func sj_any_peptide_supplement_path() -> i64 {
216 var j: i64 = 0
217 var found: i64 = 0
218 while j < SJ_N {
219 let a: i64 = sj_is_sellable(j, SI_KISSPEPTIN10)
220 let b: i64 = sj_is_sellable(j, SI_BPC157)
221 let c: i64 = sj_is_sellable(j, SI_OXYTOCIN)
222 let d: i64 = sj_is_sellable(j, SI_BREMELANOTIDE)
223 found = found + a + b + c + d
224 j = j + 1
225 }
226 if found > 0 { return 1 }
227 return 0
228}
229
230// Total indicative days and cost to open a set of markets, given the slowest
231// pathway governs launch. Returns the MAX clock (they run in parallel) and
232// the SUM of dossier costs (they do not share).
233func sj_parallel_launch_days(m0: i64, m1: i64) -> i64 {
234 let a: i64 = sj_review_days(m0)
235 let b: i64 = sj_review_days(m1)
236 if a < 0 { return SJ_INVALID }
237 if b < 0 { return SJ_INVALID }
238 if a > b { return a }
239 return b
240}
241
242func sj_combined_dossier_cost_cents(m0: i64, m1: i64) -> i64 {
243 let a: i64 = sj_dossier_cost_cents(m0)
244 let b: i64 = sj_dossier_cost_cents(m1)
245 if a < 0 { return SJ_INVALID }
246 if b < 0 { return SJ_INVALID }
247 return a + b
248}