SPB Git

spb/airiskindex Public

The most methodologically rigorous, fully transparent AI job-exposure index.

TypeScript 88% Python 6.1% SQL 2.7% CSS 1.2% JavaScript 0.9% Shell 0.8%

feat(web): full methodology documentation page + terms of service + privacy policy

Operator: Simon-Pierre Boucher, contact@spboucher.ai. Methodology page pulls
weights/version live from the scoring engine; footer links added.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
simon-pierre boucher committed 6 days ago (Aug 5, 2026) parent ad61649

Showing 4 changed files with +698 and −2

modified apps/web/app/layout.tsx +23 −2
@@ -44,8 +44,11 @@ export default async function RootLayout({
44 44 <Link href="/#ranking" className="hover:text-[var(--ink)]">
45 45 Ranking
46 46 </Link>
47 <Link href="/#concepts" className="hover:text-[var(--ink)]">
48 Method
47 + <Link href="/occupations" className="hover:text-[var(--ink)]">
48 + Browse
49 + </Link>
50 + <Link href="/methodology" className="hover:text-[var(--ink)]">
51 + Methodology
49 52 </Link>
50 53 <Link href="/api/v1/methodology" className="hover:text-[var(--ink)]">
51 54 API
@@ -62,6 +65,24 @@ export default async function RootLayout({
62 65 (CC BY 4.0, U.S. Department of Labor). This index measures task-level pressure, not
63 66 certainty of job loss — read it as adaptation guidance.
64 67 </p>
68 + <p className="mt-3 flex flex-wrap gap-x-4 gap-y-1">
69 + <Link href="/methodology" className="hover:text-[var(--ink)] hover:underline">
70 + Methodology
71 + </Link>
72 + <Link href="/terms" className="hover:text-[var(--ink)] hover:underline">
73 + Terms of Service
74 + </Link>
75 + <Link href="/privacy" className="hover:text-[var(--ink)] hover:underline">
76 + Privacy Policy
77 + </Link>
78 + <a
79 + href="mailto:contact@spboucher.ai"
80 + className="hover:text-[var(--ink)] hover:underline"
81 + >
82 + contact@spboucher.ai
83 + </a>
84 + <span>© 2026 Simon-Pierre Boucher</span>
85 + </p>
65 86 </div>
66 87 </footer>
67 88 </body>
added apps/web/app/methodology/page.tsx +448 −0
@@ -0,0 +1,448 @@
1 +import Link from "next/link";
2 +import {
3 + DIMENSIONS,
4 + EXPOSURE_DIMENSIONS,
5 + HIGH_EXPOSURE_THRESHOLD,
6 + INDEX_VERSION,
7 + INVERTED_DIMENSIONS,
8 + WEIGHTS,
9 + type DimensionKey,
10 +} from "@airiskindex/scoring";
11 +
12 +export const metadata = {
13 + title: "Methodology — AI Risk Index",
14 + description:
15 + "Full methodology of the AI Risk Index: task-based scoring, multi-model LLM rater panel, confidence intervals, weights, formulas, versioning and limitations.",
16 +};
17 +
18 +const DIMENSION_DETAILS: Array<{
19 + key: DimensionKey;
20 + name: string;
21 + question: string;
22 + anchors: string;
23 +}> = [
24 + {
25 + key: "automatability",
26 + name: "Task automatability",
27 + question:
28 + "Could current AI (including tool-using agents) perform this task end-to-end with at least 50% time saving at equal quality?",
29 + anchors:
30 + "1 = no meaningful part automatable today · 3 = roughly half automatable with significant setup · 5 = the full task meets the ≥50%-time-saving-at-equal-quality bar with off-the-shelf systems. The 50% threshold follows Eloundou et al. (2024), the citable standard.",
31 + },
32 + {
33 + key: "feasibility",
34 + name: "Current technical feasibility",
35 + question:
36 + "Do deployed products demonstrably perform this task reliably today — not merely in demos or benchmarks?",
37 + anchors:
38 + "1 = research-stage only · 3 = products exist with material error rates or narrow scope · 5 = mature products perform this reliably in production at scale. Separating conceivable from deployable is the failure that undid whole-occupation forecasts.",
39 + },
40 + {
41 + key: "cost_ratio",
42 + name: "Cost of substitution vs. wage",
43 + question:
44 + "How does the all-in AI cost per task-equivalent (inference, integration, oversight) compare to the loaded human wage for the same output?",
45 + anchors:
46 + "1 = AI is more expensive all-in · 3 = roughly comparable · 5 = AI is at least an order of magnitude cheaper.",
47 + },
48 + {
49 + key: "barriers",
50 + name: "Adoption barriers",
51 + question:
52 + "How strong are the real-world barriers to substitution: licensing and authorization requirements, liability and error-cost asymmetry, regulation of the automation itself, human-contact requirements, organizational friction?",
53 + anchors:
54 + "1 = nothing prevents substitution · 3 = some friction (oversight requirements, customer preference for humans) · 5 = hard barriers — a licensed human must legally perform or sign off on the task. This dimension is inverted in the composite: strong barriers lower the substitution score.",
55 + },
56 + {
57 + key: "adoption_velocity",
58 + name: "Sector adoption velocity",
59 + question:
60 + "How fast and deep are the sectors where this task occurs actually adopting AI — agents in production and measured displacement, not vendor announcements?",
61 + anchors:
62 + "1 = laggard sectors (small firms, physical work, low digitization) · 3 = pilots common, production rare · 5 = fast, deep adoption (information, finance, professional-services patterns).",
63 + },
64 +];
65 +
66 +function Section({
67 + id,
68 + title,
69 + children,
70 +}: {
71 + id: string;
72 + title: string;
73 + children: React.ReactNode;
74 +}): JSX.Element {
75 + return (
76 + <section id={id} className="mt-12 scroll-mt-6">
77 + <h2 className="text-2xl font-semibold tracking-tight">{title}</h2>
78 + <div className="mt-4 space-y-4 leading-relaxed text-[var(--ink-2)]">{children}</div>
79 + </section>
80 + );
81 +}
82 +
83 +export default function MethodologyPage(): JSX.Element {
84 + return (
85 + <main className="mx-auto max-w-3xl px-6 py-14">
86 + <p className="text-xs font-semibold uppercase tracking-[0.14em] text-[var(--muted)]">
87 + Methodology · version {INDEX_VERSION}
88 + </p>
89 + <h1 className="mt-3 text-4xl font-bold tracking-tight">
90 + How the AI Risk Index is computed
91 + </h1>
92 + <p className="mt-4 text-lg leading-relaxed text-[var(--ink-2)]">
93 + Every number on this site is reproducible: the weights, formulas, rater prompts and every
94 + individual model rating are public. This page is the human-readable specification; the
95 + machine-readable version is at{" "}
96 + <Link href="/api/v1/methodology" className="underline">
97 + /api/v1/methodology
98 + </Link>
99 + .
100 + </p>
101 +
102 + <nav className="mt-8 rounded-xl border border-[var(--border)] bg-[var(--surface-1)] p-5 text-sm">
103 + <p className="font-medium text-[var(--ink)]">Contents</p>
104 + <ol className="mt-2 list-inside list-decimal space-y-1 text-[var(--ink-2)]">
105 + {[
106 + ["principles", "Principles"],
107 + ["three-scores", "The three scores"],
108 + ["data", "Data sources"],
109 + ["rating", "Task rating — the multi-model panel"],
110 + ["dimensions", "The five dimensions and their weights"],
111 + ["formulas", "Formulas"],
112 + ["aggregation", "From tasks to occupations"],
113 + ["uncertainty", "Confidence intervals"],
114 + ["versioning", "Versioning and immutable runs"],
115 + ["validation", "Validation and sensitivity"],
116 + ["limitations", "Known limitations"],
117 + ["citation", "Citation, license and contact"],
118 + ].map(([anchor, label]) => (
119 + <li key={anchor}>
120 + <a href={`#${anchor}`} className="hover:text-[var(--ink)] hover:underline">
121 + {label}
122 + </a>
123 + </li>
124 + ))}
125 + </ol>
126 + </nav>
127 +
128 + <Section id="principles" title="1. Principles">
129 + <p>
130 + <strong className="text-[var(--ink)]">Task-based, not occupation-based.</strong>{" "}
131 + Occupations are bundles of tasks with very different AI exposure. Scoring whole
132 + occupations with a single judgment — the approach of the famous 2013 "47% of jobs"
133 + estimate — has a poor empirical track record. We score each of the ~18,800 O*NET task
134 + statements individually and derive occupation scores from them, weighted by how
135 + important each task is to the occupation.
136 + </p>
137 + <p>
138 + <strong className="text-[var(--ink)]">Uncertainty is part of the score.</strong> Large
139 + language models disagree with each other substantially when rating AI exposure —
140 + replications show the share of "highly exposed" occupations can vary by an order of
141 + magnitude depending on which frontier model does the rating. A single-model index is
142 + therefore an artifact. Every score we publish carries a confidence interval derived from
143 + disagreement across an independent multi-model panel.
144 + </p>
145 + <p>
146 + <strong className="text-[var(--ink)]">Fully reproducible.</strong> Weights live in one
147 + versioned source file, prompts are versioned, every rating stores the model, prompt
148 + version, raw response and parsed score, and every published number traces to a stored,
149 + immutable computation run.
150 + </p>
151 + <p>
152 + <strong className="text-[var(--ink)]">Adaptation, not doom.</strong> The evidence to
153 + date shows concentrated, cohort-specific effects — especially on entry-level hiring in
154 + automation-exposed occupations — rather than economy-wide job loss, while measured AI
155 + usage remains majority-augmentative. The index is designed to guide adaptation
156 + decisions, not to produce headlines.
157 + </p>
158 + </Section>
159 +
160 + <Section id="three-scores" title="2. The three scores">
161 + <p>Every occupation gets three sub-scores on a 0–100 scale, never collapsed into one:</p>
162 + <ul className="list-inside list-disc space-y-2">
163 + <li>
164 + <strong className="text-[var(--ink)]">Exposure</strong> — AI is technically capable of
165 + performing the occupation's tasks. Computed from the capability dimensions only
166 + (automatability and feasibility).
167 + </li>
168 + <li>
169 + <strong className="text-[var(--ink)]">Substitution</strong> — the headline composite:
170 + AI actually replaces the human, once cost, adoption barriers and sector adoption
171 + velocity are accounted for. Exposure without adoption predicts nothing; this score is
172 + exposure discounted by the real world.
173 + </li>
174 + <li>
175 + <strong className="text-[var(--ink)]">Augmentation</strong> — AI assists the human on
176 + the task, raising productivity without replacing them. Rated separately per task; it
177 + is not part of the substitution composite. High augmentation alongside moderate
178 + substitution reads as a changing job, not a disappearing one.
179 + </li>
180 + </ul>
181 + </Section>
182 +
183 + <Section id="data" title="3. Data sources">
184 + <div className="overflow-x-auto rounded-xl border border-[var(--border)] bg-[var(--surface-1)]">
185 + <table className="w-full text-left text-sm">
186 + <thead className="border-b border-[var(--grid)] text-xs uppercase tracking-wide text-[var(--muted)]">
187 + <tr>
188 + <th className="px-4 py-3 font-medium">Input</th>
189 + <th className="px-4 py-3 font-medium">Source</th>
190 + <th className="px-4 py-3 font-medium">Role</th>
191 + </tr>
192 + </thead>
193 + <tbody>
194 + {[
195 + [
196 + "Occupations & task statements",
197 + "O*NET 30.3 (U.S. Dept. of Labor, CC BY 4.0), O*NET-SOC 2019 taxonomy",
198 + "Unit of analysis: 1,016 occupations, ~18,800 tasks",
199 + ],
200 + [
201 + "Task importance weights",
202 + "O*NET Task Ratings, importance scale (IM, 1–5)",
203 + "Aggregation weights from tasks to occupations",
204 + ],
205 + [
206 + "Wages & employment",
207 + "BLS Occupational Employment and Wage Statistics, May 2025 national",
208 + "Median wages (shown per occupation; cost-ratio context)",
209 + ],
210 + [
211 + "EU/France crosswalk (planned)",
212 + "ESCO v1.2 + official ESCO↔O*NET crosswalk; ROME 4.0",
213 + "European occupation coverage in a future release",
214 + ],
215 + [
216 + "Adoption evidence",
217 + "Census BTOS, Anthropic Economic Index, sector deployment studies",
218 + "Grounding for the adoption-velocity rubric anchors",
219 + ],
220 + ].map(([a, b, c]) => (
221 + <tr key={a as string} className="border-b border-[var(--grid)] last:border-b-0 align-top">
222 + <td className="px-4 py-3 font-medium text-[var(--ink)]">{a}</td>
223 + <td className="px-4 py-3">{b}</td>
224 + <td className="px-4 py-3">{c}</td>
225 + </tr>
226 + ))}
227 + </tbody>
228 + </table>
229 + </div>
230 + <p>
231 + Raw source dumps are immutable and never edited in place; all transformations run
232 + through a pipeline that records manifests (hashes and row counts) for every derived
233 + artifact.
234 + </p>
235 + </Section>
236 +
237 + <Section id="rating" title="4. Task rating — the multi-model panel">
238 + <p>
239 + Each task statement is rated on six dimensions (the five composite dimensions plus
240 + augmentation) on an integer 1–5 scale by{" "}
241 + <strong className="text-[var(--ink)]">at least two independent frontier language
242 + models</strong> using an identical, versioned rubric prompt. Ratings are requested with
243 + schema-constrained JSON output; each rating must include a written rationale grounded in
244 + the task statement.
245 + </p>
246 + <p>
247 + For every task × dimension, the panel produces a rating band:{" "}
248 + <code>low</code> = the panel minimum, <code>mid</code> = the panel mean,{" "}
249 + <code>high</code> = the panel maximum. Bands — not single numbers — flow into all
250 + downstream computation, which is how rater disagreement becomes a visible confidence
251 + interval instead of hidden noise.
252 + </p>
253 + <p>
254 + <strong className="text-[var(--ink)]">Audit trail.</strong> Every rating stores the
255 + model identifier, prompt version, raw API response, parsed score and rationale. On any
256 + occupation page, expanding a task shows every model's rating and rationale — nothing is
257 + asserted that cannot be inspected.
258 + </p>
259 + <p>
260 + <strong className="text-[var(--ink)]">Human validation.</strong> A sample of ratings is
261 + reviewed by humans; disagreements above one point on the 5-point scale route the task to
262 + an expert review queue whose overrides replace the model band and are flagged in the
263 + data. Prompt changes bump the prompt version and invalidate cached ratings.
264 + </p>
265 + </Section>
266 +
267 + <Section id="dimensions" title="5. The five dimensions and their weights">
268 + <div className="overflow-x-auto rounded-xl border border-[var(--border)] bg-[var(--surface-1)]">
269 + <table className="w-full text-left text-sm">
270 + <thead className="border-b border-[var(--grid)] text-xs uppercase tracking-wide text-[var(--muted)]">
271 + <tr>
272 + <th className="px-4 py-3 font-medium">Dimension</th>
273 + <th className="px-4 py-3 font-medium">Weight</th>
274 + <th className="px-4 py-3 font-medium">Orientation</th>
275 + </tr>
276 + </thead>
277 + <tbody className="tabular-nums">
278 + {DIMENSIONS.map((key) => (
279 + <tr key={key} className="border-b border-[var(--grid)] last:border-b-0">
280 + <td className="px-4 py-3 font-medium text-[var(--ink)]">
281 + {DIMENSION_DETAILS.find((d) => d.key === key)?.name ?? key}
282 + </td>
283 + <td className="px-4 py-3">{(WEIGHTS[key] * 100).toFixed(0)}%</td>
284 + <td className="px-4 py-3">
285 + {INVERTED_DIMENSIONS.has(key)
286 + ? "inverted — higher rating lowers substitution"
287 + : "direct"}
288 + </td>
289 + </tr>
290 + ))}
291 + </tbody>
292 + </table>
293 + </div>
294 + <div className="space-y-5">
295 + {DIMENSION_DETAILS.map((dim) => (
296 + <div key={dim.key}>
297 + <h3 className="font-semibold text-[var(--ink)]">
298 + {dim.name}{" "}
299 + <span className="text-sm font-normal text-[var(--muted)]">
300 + · weight {(WEIGHTS[dim.key] * 100).toFixed(0)}%
301 + </span>
302 + </h3>
303 + <p className="mt-1">{dim.question}</p>
304 + <p className="mt-1 text-sm text-[var(--muted)]">{dim.anchors}</p>
305 + </div>
306 + ))}
307 + </div>
308 + <p>
309 + Weights are defined once, in a versioned source file, and served live at{" "}
310 + <Link href="/api/v1/methodology" className="underline">
311 + /api/v1/methodology
312 + </Link>{" "}
313 + — any change is a new index version with a changelog entry and regenerated sensitivity
314 + analyses.
315 + </p>
316 + </Section>
317 +
318 + <Section id="formulas" title="6. Formulas">
319 + <p>
320 + A rating <em>r</em> ∈ [1, 5] normalizes to substitution pressure <em>p</em> ∈ [0, 1]:
321 + </p>
322 + <pre className="overflow-x-auto rounded-xl border border-[var(--border)] bg-[var(--surface-1)] p-4 text-sm text-[var(--ink)]">
323 + {`p = (r − 1) / 4 direct dimensions
324 +p = 1 − (r − 1) / 4 inverted dimensions (barriers)
325 +
326 +substitution_task = 100 · Σ_d w_d · p_d over all five dimensions
327 +exposure_task = 100 · (w_auto·p_auto + w_feas·p_feas) / (w_auto + w_feas)
328 +augmentation_task = 100 · p_augmentation`}
329 + </pre>
330 + <p>
331 + The exposure sub-score uses only {EXPOSURE_DIMENSIONS.join(" and ")}, renormalized. The
332 + scoring engine is a pure, deterministic library with no network, clock or randomness —
333 + identical inputs always produce identical scores, which is what makes runs auditable.
334 + Its behavior is pinned by property-based tests and by a published worked example that
335 + the test suite reproduces to three decimals.
336 + </p>
337 + </Section>
338 +
339 + <Section id="aggregation" title="7. From tasks to occupations">
340 + <p>
341 + Occupation scores are the importance-weighted mean of task scores, using O*NET task
342 + importance ratings normalized within each occupation. Tasks without an importance rating
343 + receive the occupation's mean importance. The same aggregation applies to the low, mid
344 + and high bounds.
345 + </p>
346 + <p>
347 + We additionally report the <strong className="text-[var(--ink)]">highly exposed task
348 + share</strong>: the fraction of an occupation's tasks with a substitution score of{" "}
349 + {HIGH_EXPOSURE_THRESHOLD} or more. "X% of tasks in this occupation are highly exposed"
350 + is the preferred headline reading — more honest than a single composite.
351 + </p>
352 + </Section>
353 +
354 + <Section id="uncertainty" title="8. Confidence intervals">
355 + <p>
356 + The low and high bounds are worst/best-case envelopes over the rater panel: the lower
357 + bound takes each dimension's pressure-minimizing rating bound (for the inverted barriers
358 + dimension, that is the <em>high</em> rating), the upper bound symmetrically. By
359 + construction low ≤ score ≤ high always holds. A wide interval means the models disagreed
360 + — treat that score as an open question, not a verdict. Occupations with the widest
361 + intervals are exactly where human expert review is prioritized.
362 + </p>
363 + </Section>
364 +
365 + <Section id="versioning" title="9. Versioning and immutable runs">
366 + <p>
367 + The index version ({INDEX_VERSION}) follows semantic versioning: formula or weight
368 + changes are major; data-source refreshes are minor; recomputations with refreshed
369 + adoption inputs are patches. Every computation writes a run record with the index
370 + version, prompt version and rater models. Runs are immutable — recomputations create new
371 + runs and old runs remain queryable, so any historically published score can be
372 + reproduced and checked forever. Every API response carries the index version it was
373 + computed under.
374 + </p>
375 + </Section>
376 +
377 + <Section id="validation" title="10. Validation and sensitivity">
378 + <p>Published alongside each major or minor release:</p>
379 + <ul className="list-inside list-disc space-y-2">
380 + <li>
381 + <strong className="text-[var(--ink)]">Convergent validity</strong> — rank correlation
382 + against independent published measures (Felten AIOE, "GPTs are GPTs" task scores, ILO
383 + exposure gradients).
384 + </li>
385 + <li>
386 + <strong className="text-[var(--ink)]">Rater stability</strong> — the distribution of
387 + cross-model agreement; the widest-band occupations are flagged in the product.
388 + </li>
389 + <li>
390 + <strong className="text-[var(--ink)]">Outcome tracking</strong> — correlation against
391 + realized labor-market indicators (entry-level employment in exposed occupations,
392 + measured usage data). Exposure indices individually explain little of realized
393 + unemployment risk, so we report outcome tracking honestly rather than claiming
394 + prediction.
395 + </li>
396 + <li>
397 + <strong className="text-[var(--ink)]">Weight sensitivity</strong> — rank stability of
398 + the composite under ±25% perturbation of each weight.
399 + </li>
400 + </ul>
401 + </Section>
402 +
403 + <Section id="limitations" title="11. Known limitations">
404 + <ul className="list-inside list-disc space-y-2">
405 + <li>
406 + LLM raters co-evolve with the technology they measure; multi-model panels bound this
407 + "ruler problem" but do not eliminate it.
408 + </li>
409 + <li>
410 + Sector-level adoption evidence enters through rubric anchors rather than per-sector
411 + statistical joins in the current version.
412 + </li>
413 + <li>
414 + Scores describe tasks as currently constituted; occupations reorganize, and task mixes
415 + shift precisely when exposure is high.
416 + </li>
417 + <li>
418 + Wages shown are U.S. national medians; cross-country generalization awaits the
419 + ESCO/ROME release.
420 + </li>
421 + <li>
422 + This index measures pressure, not destiny. It cannot tell an individual whether their
423 + job is safe; it can tell them which of their tasks are changing and how confident the
424 + evidence is.
425 + </li>
426 + </ul>
427 + </Section>
428 +
429 + <Section id="citation" title="12. Citation, license and contact">
430 + <p>
431 + Cite as: <em>AI Risk Index, version {INDEX_VERSION}, airiskindex.io, Simon-Pierre
432 + Boucher (2026)</em>. Scores and derived data are published under{" "}
433 + <strong className="text-[var(--ink)]">CC BY 4.0</strong> — reuse freely with
434 + attribution and the index version. Occupation and task data incorporate the O*NET
435 + database (U.S. Department of Labor, CC BY 4.0); wage data from BLS OEWS.
436 + </p>
437 + <p>
438 + Methodology questions, corrections, expert-panel participation, data licensing or
439 + anything else:{" "}
440 + <a href="mailto:contact@spboucher.ai" className="underline">
441 + contact@spboucher.ai
442 + </a>{" "}
443 + — Simon-Pierre Boucher.
444 + </p>
445 + </Section>
446 + </main>
447 + );
448 +}
added apps/web/app/privacy/page.tsx +99 −0
@@ -0,0 +1,99 @@
1 +export const metadata = {
2 + title: "Privacy Policy — AI Risk Index",
3 +};
4 +
5 +function Section({ title, children }: { title: string; children: React.ReactNode }): JSX.Element {
6 + return (
7 + <section className="mt-8">
8 + <h2 className="text-xl font-semibold tracking-tight">{title}</h2>
9 + <div className="mt-3 space-y-3 leading-relaxed text-[var(--ink-2)]">{children}</div>
10 + </section>
11 + );
12 +}
13 +
14 +export default function PrivacyPage(): JSX.Element {
15 + return (
16 + <main className="mx-auto max-w-3xl px-6 py-14">
17 + <h1 className="text-4xl font-bold tracking-tight">Privacy Policy</h1>
18 + <p className="mt-3 text-sm text-[var(--muted)]">Effective date: August 5, 2026</p>
19 + <p className="mt-4 leading-relaxed text-[var(--ink-2)]">
20 + This policy describes how the AI Risk Index (www.airiskindex.io), operated by{" "}
21 + <strong className="text-[var(--ink)]">Simon-Pierre Boucher</strong>, handles personal
22 + information. The short version: the site works without an account, we collect almost
23 + nothing, we track nobody, and we sell nothing.
24 + </p>
25 +
26 + <Section title="1. What we collect">
27 + <ul className="list-inside list-disc space-y-2">
28 + <li>
29 + <strong className="text-[var(--ink)]">Server and access logs</strong> — IP address,
30 + user agent, requested URL and timestamp, kept for security, debugging and rate
31 + limiting, and routinely deleted within 30 days.
32 + </li>
33 + <li>
34 + <strong className="text-[var(--ink)]">API keys</strong> — if you request one, we store
35 + your contact email and a hashed key. We never store keys in plaintext.
36 + </li>
37 + <li>
38 + <strong className="text-[var(--ink)]">Email</strong> — if you write to us, we keep the
39 + correspondence for as long as needed to handle it.
40 + </li>
41 + </ul>
42 + <p>
43 + We do not use advertising trackers or third-party analytics, we set no cookies for
44 + browsing, and we do not profile visitors. Occupation pages you view are not linked to
45 + you.
46 + </p>
47 + </Section>
48 +
49 + <Section title="2. What we don't do">
50 + <p>
51 + We do not sell, rent or share personal information with third parties for their own
52 + purposes. We do not use your data to train models. Occupation scores are computed from
53 + public occupational data — never from visitor data.
54 + </p>
55 + </Section>
56 +
57 + <Section title="3. Infrastructure providers">
58 + <p>
59 + Traffic to the site transits through our tunnel/edge provider (ngrok) to our servers;
60 + their systems process connection metadata as any network carrier does. No visitor data
61 + is sent to AI model providers — model APIs are used only to rate public occupational
62 + task statements.
63 + </p>
64 + </Section>
65 +
66 + <Section title="4. Your rights">
67 + <p>
68 + Under Québec's Act respecting the protection of personal information in the private
69 + sector (Law 25), the GDPR where it applies, and similar laws, you may request access to,
70 + correction of, or deletion of personal information we hold about you (in practice: log
71 + entries, an API key record, or email correspondence). Write to{" "}
72 + <a href="mailto:contact@spboucher.ai" className="underline">
73 + contact@spboucher.ai
74 + </a>{" "}
75 + and we will respond within 30 days.
76 + </p>
77 + </Section>
78 +
79 + <Section title="5. Data location and security">
80 + <p>
81 + Data is processed on servers under our control (Canada) and protected by access
82 + controls, key hashing and encrypted transport (HTTPS). No system is perfectly secure; we
83 + keep the collected surface deliberately minimal so there is little to lose.
84 + </p>
85 + </Section>
86 +
87 + <Section title="6. Changes">
88 + <p>
89 + Material changes to this policy are indicated by the effective date above. The person
90 + responsible for the protection of personal information is Simon-Pierre Boucher —{" "}
91 + <a href="mailto:contact@spboucher.ai" className="underline">
92 + contact@spboucher.ai
93 + </a>
94 + .
95 + </p>
96 + </Section>
97 + </main>
98 + );
99 +}
added apps/web/app/terms/page.tsx +128 −0
@@ -0,0 +1,128 @@
1 +export const metadata = {
2 + title: "Terms of Service — AI Risk Index",
3 +};
4 +
5 +function Section({ title, children }: { title: string; children: React.ReactNode }): JSX.Element {
6 + return (
7 + <section className="mt-8">
8 + <h2 className="text-xl font-semibold tracking-tight">{title}</h2>
9 + <div className="mt-3 space-y-3 leading-relaxed text-[var(--ink-2)]">{children}</div>
10 + </section>
11 + );
12 +}
13 +
14 +export default function TermsPage(): JSX.Element {
15 + return (
16 + <main className="mx-auto max-w-3xl px-6 py-14">
17 + <h1 className="text-4xl font-bold tracking-tight">Terms of Service</h1>
18 + <p className="mt-3 text-sm text-[var(--muted)]">Effective date: August 5, 2026</p>
19 + <p className="mt-4 leading-relaxed text-[var(--ink-2)]">
20 + The AI Risk Index website and API (the "Service", at www.airiskindex.io) are operated by{" "}
21 + <strong className="text-[var(--ink)]">Simon-Pierre Boucher</strong> ("we", "us"). By
22 + accessing the Service you agree to these terms. Contact for any question, including
23 + contracts and licensing:{" "}
24 + <a href="mailto:contact@spboucher.ai" className="underline">
25 + contact@spboucher.ai
26 + </a>
27 + .
28 + </p>
29 +
30 + <Section title="1. What the Service is">
31 + <p>
32 + The Service publishes research-grade estimates of occupational exposure to AI, computed
33 + from public occupational data and model-based task ratings under a documented,
34 + versioned methodology. Scores are statistical claims with confidence intervals — they
35 + describe task-level pressure, not the future of any individual's job.
36 + </p>
37 + </Section>
38 +
39 + <Section title="2. Not professional advice">
40 + <p>
41 + Nothing on the Service is career, financial, legal, or employment advice. Scores must
42 + not be used as the sole basis for employment decisions about identifiable individuals —
43 + including hiring, dismissal, promotion, compensation, or automated screening. If you
44 + use the data in decision systems, you are responsible for compliance with applicable
45 + employment and AI regulations in your jurisdiction.
46 + </p>
47 + </Section>
48 +
49 + <Section title="3. Accuracy and warranties">
50 + <p>
51 + The Service is provided "as is" and "as available", without warranty of any kind,
52 + express or implied, including merchantability, fitness for a particular purpose, and
53 + non-infringement. Model-based ratings contain errors by nature; confidence intervals
54 + quantify part of that uncertainty, not all of it. We may correct, recompute, or
55 + re-version scores at any time; historical runs remain identified by version.
56 + </p>
57 + </Section>
58 +
59 + <Section title="4. API use">
60 + <p>
61 + The public API is rate-limited (currently 60 requests/minute unauthenticated; higher
62 + limits with an API key). You may not circumvent rate limits, resell raw API access, or
63 + misrepresent Service data as your own measurements. Breaking changes are only introduced
64 + under new API versions.
65 + </p>
66 + </Section>
67 +
68 + <Section title="5. Licenses and attribution">
69 + <p>
70 + Scores and derived datasets are licensed under{" "}
71 + <a href="https://creativecommons.org/licenses/by/4.0/" className="underline">
72 + CC BY 4.0
73 + </a>
74 + : reuse, redistribution and commercial use are permitted with attribution to "AI Risk
75 + Index (airiskindex.io)" and the index version. Site design and text are ©{" "}
76 + Simon-Pierre Boucher. The Service incorporates the O*NET® database (U.S. Department of
77 + Labor, Employment and Training Administration, CC BY 4.0) and BLS OEWS data; O*NET® is a
78 + trademark of USDOL/ETA, which has not reviewed or endorsed this Service.
79 + </p>
80 + </Section>
81 +
82 + <Section title="6. Acceptable use">
83 + <p>
84 + You agree not to: disrupt or overload the Service; probe or breach its security; scrape
85 + at rates exceeding the API limits when an API exists for the purpose; or use the Service
86 + to produce deceptive content that misattributes claims to us.
87 + </p>
88 + </Section>
89 +
90 + <Section title="7. Limitation of liability">
91 + <p>
92 + To the maximum extent permitted by law, we are not liable for indirect, incidental,
93 + special, consequential or punitive damages, nor for lost profits, revenues, data or
94 + goodwill, arising from use of the Service. Our aggregate liability for any claim is
95 + limited to one hundred Canadian dollars (CAD 100). Some jurisdictions do not allow
96 + certain exclusions; where they apply, these limits apply to the fullest extent
97 + permitted.
98 + </p>
99 + </Section>
100 +
101 + <Section title="8. Changes and termination">
102 + <p>
103 + We may modify or discontinue the Service, or update these terms, at any time; material
104 + changes are indicated by the effective date above. Continued use after a change
105 + constitutes acceptance. We may suspend access that violates these terms.
106 + </p>
107 + </Section>
108 +
109 + <Section title="9. Governing law">
110 + <p>
111 + These terms are governed by the laws of the Province of Québec and the federal laws of
112 + Canada applicable therein. Disputes are subject to the exclusive jurisdiction of the
113 + courts of Québec, Canada.
114 + </p>
115 + </Section>
116 +
117 + <Section title="10. Contact">
118 + <p>
119 + Simon-Pierre Boucher —{" "}
120 + <a href="mailto:contact@spboucher.ai" className="underline">
121 + contact@spboucher.ai
122 + </a>{" "}
123 + (including commercial licensing, data partnerships and contracts).
124 + </p>
125 + </Section>
126 + </main>
127 + );
128 +}
129