+ {children}
+
+ );
+}
+```
+
+- [ ] **Step 2: Create `site-footer.tsx`**
+
+```tsx
+import Link from "next/link";
+
+export function SiteFooter() {
+ return (
+
+ );
+}
+```
+
+- [ ] **Step 3: Wire the footer into the layout**
+
+In `frontend/src/app/layout.tsx`: add the import `import { SiteFooter } from "@/components/site-footer";` alongside the other component imports, and render `` as the LAST child of ``, after the `` closing tag. The `` should read:
+
+```tsx
+
+
+
+ {children}
+
+
+
+```
+
+- [ ] **Step 4: Typecheck + build (verify the footer doesn't break the layout)**
+
+Run: `npx tsc --noEmit`
+Expected: clean.
+
+Run: `npm run build`
+Expected: build succeeds; `/` still listed (static), no new errors.
+
+- [ ] **Step 5: Visual check (manual)**
+
+Start `npm run dev`, open `/` — confirm the landing hero is still centered and the footer sits unobtrusively at the bottom; check at a mobile width (~375px) that the footer stacks (column) and reads cleanly. (If the dev server can't run in this environment, note it — the build + later test cover structure; visual is the operator's quick confirm.)
+
+- [ ] **Step 6: Commit**
+
+```bash
+git add frontend/src/components/legal-prose.tsx frontend/src/components/site-footer.tsx frontend/src/app/layout.tsx
+git commit -m "feat(v0.9.7): global site footer + legal-prose wrapper"
+```
+
+---
+
+### Task 2: Privacy Policy page
+
+**Files:**
+- Create: `frontend/src/app/privacy/page.tsx`
+
+- [ ] **Step 1: Create the page**
+
+```tsx
+import type { Metadata } from "next";
+import { LegalProse, LegalSection } from "@/components/legal-prose";
+
+export const metadata: Metadata = {
+ title: "Privacy Policy — Skill Issue",
+ description: "What Skill Issue collects, how it's used, and your choices.",
+};
+
+const EMAIL = "shaansatsangi.cse@gmail.com";
+
+export default function PrivacyPage() {
+ return (
+
+
+ Skill Issue is operated by Shaan Satsangi (“we”). This policy explains, in plain
+ language, what we collect, why, and the choices you have. We collect as little as we need to
+ run the service.
+
+
+
+
+
+ GitHub profile (if you sign in). We use
+ GitHub OAuth with read-only read:user scope to read your public profile
+ (login, name, avatar). Your GitHub access token is encrypted at rest.
+
+
+ Analyses and history. When signed in, the
+ analyses you run are saved to your history until you delete them.
+
+
+ IP address. Used transiently to rate-limit
+ requests and prevent abuse.
+
+
+ Usage and error data. Aggregate product
+ analytics and error reports help us keep the service working.
+
+
+ A session cookie. Keeps you signed in.
+
+
+
+
+
+
+ To generate and display your report, save your history when you’re signed in, prevent
+ abuse, and improve reliability. We do not sell your data or use it for advertising.
+
+
+
+
+
We rely on a few service providers to run Skill Issue:
+
+
GitHub — the source of the public data we analyze.
+
Vercel — hosting.
+
Neon — database (accounts, saved analyses).
+
Upstash — short-lived caching and rate-limit counters.
+
Groq — generates the AI narrative from your report.
+
Sentry — error monitoring.
+
PostHog — product analytics.
+
+
+
+
+
+ Sign-in sessions expire after about 30 days. Saved analyses stay until you delete them.
+ Caches are short-lived and expire automatically.
+
+
+
+
+
+ You can delete saved analyses from your history, sign out at any time, and revoke
+ Skill Issue’s access from your{" "}
+
+ GitHub application settings
+
+ .
+
+
+
+
+
+ We use a session cookie to keep you signed in and a short-lived cookie during the GitHub
+ sign-in flow. We do not use advertising or cross-site tracking cookies.
+
+
+
+
+
Skill Issue is intended for users aged 13 and older, consistent with GitHub.
+
+
+
+
+ We may update this policy; the “last updated” date above reflects the latest
+ version.
+
+
+
+ );
+}
+```
+
+- [ ] **Step 2: Typecheck**
+
+Run: `npx tsc --noEmit`
+Expected: clean.
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add frontend/src/app/privacy/page.tsx
+git commit -m "feat(v0.9.7): privacy policy page"
+```
+
+---
+
+### Task 3: Terms of Service page
+
+**Files:**
+- Create: `frontend/src/app/terms/page.tsx`
+
+- [ ] **Step 1: Create the page**
+
+```tsx
+import type { Metadata } from "next";
+import { LegalProse, LegalSection } from "@/components/legal-prose";
+
+export const metadata: Metadata = {
+ title: "Terms of Service — Skill Issue",
+ description: "The terms for using Skill Issue.",
+};
+
+const EMAIL = "shaansatsangi.cse@gmail.com";
+
+export default function TermsPage() {
+ return (
+
+
+ By using Skill Issue (operated by Shaan Satsangi), you agree to these terms. If you
+ don’t agree, please don’t use the service.
+
+
+
+
+ Skill Issue produces an opinionated, automated analysis of a public GitHub profile for
+ insight and entertainment. The scores and commentary are generated by software and may be
+ incomplete or wrong. Skill Issue is not an
+ authoritative hiring, credit, employment, or background-check tool, and should not be used
+ to make decisions about people.
+
+
+
+
+
+ Signing in is optional and uses GitHub OAuth. You are responsible for activity under your
+ GitHub account and for keeping it secure.
+
+
+
+
+
You agree not to:
+
+
abuse, overload, or attempt to disrupt the service;
+
scrape it or access it through automated means outside normal use;
+
circumvent rate limits or security measures;
+
use it to harass others or for unlawful purposes.
+
+
+
+
+
+ The service, its design, and its scoring system belong to us. GitHub data shown in a report
+ belongs to its respective owners and GitHub; we present it for analysis.
+
+
+
+
+
+ The service is provided “as is” and “as available,” without
+ warranties of any kind. Scores are subjective, automated estimates and are not guarantees
+ of skill, quality, or fitness for any purpose.
+
+
+
+
+
+ To the maximum extent permitted by law, we are not liable for any indirect, incidental, or
+ consequential damages arising from your use of the service.
+
+
+
+
+
+ We may suspend or limit access that abuses the service. You can stop using it and delete
+ your saved data at any time.
+
+
+
+
+
These terms are governed by the laws of India.
+
+
+
+
+ We may update these terms; the “last updated” date above reflects the latest
+ version. Continued use means you accept the changes.
+
+
+
+ );
+}
+```
+
+- [ ] **Step 2: Typecheck**
+
+Run: `npx tsc --noEmit`
+Expected: clean.
+
+- [ ] **Step 3: Commit**
+
+```bash
+git add frontend/src/app/terms/page.tsx
+git commit -m "feat(v0.9.7): terms of service page"
+```
+
+---
+
+### Task 4: Smoke tests + docs/legal pointer
+
+**Files:**
+- Create: `frontend/src/components/__tests__/legal-pages.test.tsx`, `docs/legal/README.md`
+
+- [ ] **Step 1: Write the tests**
+
+```tsx
+import { render, screen } from "@testing-library/react";
+import { describe, it, expect } from "vitest";
+import PrivacyPage from "@/app/privacy/page";
+import TermsPage from "@/app/terms/page";
+import { SiteFooter } from "@/components/site-footer";
+
+describe("legal pages", () => {
+ it("privacy page shows its heading and the contact email", () => {
+ render();
+ expect(
+ screen.getByRole("heading", { name: /privacy policy/i, level: 1 }),
+ ).toBeInTheDocument();
+ expect(screen.getByText("shaansatsangi.cse@gmail.com")).toBeInTheDocument();
+ });
+
+ it("terms page shows its heading and the governing law", () => {
+ render();
+ expect(
+ screen.getByRole("heading", { name: /terms of service/i, level: 1 }),
+ ).toBeInTheDocument();
+ expect(screen.getByText(/laws of India/i)).toBeInTheDocument();
+ });
+
+ it("footer links to privacy and terms", () => {
+ render();
+ expect(screen.getByRole("link", { name: /privacy/i })).toHaveAttribute("href", "/privacy");
+ expect(screen.getByRole("link", { name: /terms/i })).toHaveAttribute("href", "/terms");
+ });
+});
+```
+
+- [ ] **Step 2: Run the tests**
+
+Run: `npm run test:run -- legal-pages`
+Expected: 3 passed. (If `next/link` needs no special handling, this works under the existing happy-dom setup; the pages are sync server components with no async or server-only APIs, so RTL renders them directly.)
+
+- [ ] **Step 3: Create `docs/legal/README.md`**
+
+```markdown
+# Legal
+
+The Privacy Policy and Terms of Service are maintained as rendered pages (single
+source of truth — no markdown duplicate to drift):
+
+- Privacy Policy: [`frontend/src/app/privacy/page.tsx`](../../frontend/src/app/privacy/page.tsx) → `/privacy`
+- Terms of Service: [`frontend/src/app/terms/page.tsx`](../../frontend/src/app/terms/page.tsx) → `/terms`
+
+Last updated: 2026-05-28. Lightweight, plain-language drafts grounded in the
+app's actual data practices — **not legal advice**; have a professional review
+before relying on them.
+```
+
+- [ ] **Step 4: Commit**
+
+```bash
+git add frontend/src/components/__tests__/legal-pages.test.tsx docs/legal/README.md
+git commit -m "test(v0.9.7): legal page smoke tests + docs/legal pointer"
+```
+
+---
+
+### Task 5: Docs ritual + version bump + ship
+
+**Files:**
+- Modify: `backend/pyproject.toml:3`, `backend/app/settings.py:5`, `frontend/package.json:3`, `frontend/src/app/page.tsx:26`, `frontend/src/components/results-view.tsx:355`, `README.md` (status lead + running list + health curl), `CHANGELOG.md`, `PLAN.md` (v0.9.7 row + section), `docs/PROGRESS_LOG.md`, `backend/uv.lock`
+
+- [ ] **Step 1: Bump version literals**
+
+`backend/pyproject.toml` line 3 `version = "0.9.6"` → `"0.9.7"`; `backend/app/settings.py` line 5 `VERSION = "0.9.6"` → `"0.9.7"`; `frontend/package.json` line 3 `"version": "0.9.6",` → `"0.9.7",`; `frontend/src/app/page.tsx` line 26 `... · v0.9.6` → `v0.9.7`; `frontend/src/components/results-view.tsx` line 355 `... Protocol v0.9.6` → `v0.9.7`.
+
+- [ ] **Step 2: Update README**
+
+`README.md` line 46: change the lead `Latest shipped release is **v0.9.6** (...)` to name **v0.9.7** (privacy policy + terms of service pages with a global footer), demote v0.9.6 to "before it," and change the trailing pointer from `**v0.9.7 — privacy policy + terms** is next.` to `v0.9.7 adds a Privacy Policy and Terms of Service (linked from a new global footer). **v1.0.0 — public launch** is next.` Bump the health-curl `"version":"0.9.6"` → `"0.9.7"` (line ~79).
+
+- [ ] **Step 3: Add the CHANGELOG entry**
+
+In `CHANGELOG.md`, insert below the preamble `---` and above `## [0.9.6]`:
+
+```markdown
+## [0.9.7] — 2026-05-28
+
+### Added
+- **Privacy Policy and Terms of Service.** Plain-language legal pages at `/privacy` and `/terms`, linked from a new site-wide footer.
+
+---
+```
+
+- [ ] **Step 4: Update PLAN.md**
+
+Version-map row `| **v0.9.7** | Privacy policy + terms (legal docs) | pending |` → `| **v0.9.7** | Privacy policy + terms + global footer | ✅ shipped |`.
+
+Replace the `## v0.9.7 — Legal docs (deferred)` section body (Goal + "Exit criteria: TBD") with:
+
+```markdown
+## v0.9.7 — Privacy + Terms (shipped 2026-05-28)
+
+**Goal:** Plain-language Privacy Policy + Terms of Service pages, linked from a new global footer.
+
+**Delivered:** Static TSX pages `/privacy` + `/terms` (shared `LegalProse` wrapper), a global `SiteFooter`, content grounded in the app's real data practices (GitHub `read:user`, Neon, Upstash, Groq, Sentry, PostHog), India governing law, 13+, contact shaansatsangi.cse@gmail.com. Not legal advice — flagged for professional review before launch.
+
+**Design spec:** [`docs/superpowers/specs/2026-05-28-v0.9.7-legal-docs-design.md`](./docs/superpowers/specs/2026-05-28-v0.9.7-legal-docs-design.md).
+**Sub-plan:** [`docs/superpowers/plans/2026-05-28-v0.9.7-legal-docs.md`](./docs/superpowers/plans/2026-05-28-v0.9.7-legal-docs.md).
+
+**Exit criteria:**
+- [x] `/privacy` + `/terms` render via `LegalProse`; metadata + "Last updated 2026-05-28".
+- [x] Global `SiteFooter` links both (+ GitHub); landing hero intact; mobile verified.
+- [x] Smoke tests pass; frontend lint/tsc/test/build clean.
+- [x] Docs ritual + version bump to 0.9.7; tag + release.
+```
+
+- [ ] **Step 5: Re-sync `uv.lock`**
+
+Run: `cd backend && uv lock`
+Expected: only `skill-issue-backend 0.9.6 → 0.9.7` changes.
+
+- [ ] **Step 6: Add the PROGRESS_LOG entry**
+
+In `docs/PROGRESS_LOG.md`, add a new top entry per the file's format: header `## 2026-05-28 — Claude (Opus 4.7) — v0.9.7 shipped (privacy + terms)`; Slice v0.9.7; Done (the two pages + footer + LegalProse + tests + docs/legal pointer); Decisions (static TSX over markdown — no dep, single source; lightweight India/13+ per user; global footer added since none existed; not-legal-advice flagged); Verified (lint/tsc/test/build + visual); Blocked/open (professional legal review recommended pre-launch); Next (v1.0.0 public launch).
+
+- [ ] **Step 7: Full verification**
+
+Run: `cd frontend && npm run lint && npx tsc --noEmit && npm run test:run && npm run build`
+Expected: lint/tsc clean; vitest 54 + 3 new = 57 passed; build succeeds with `/privacy` and `/terms` listed (static).
+
+Run: `cd backend && uv run pytest -q --no-header`
+Expected: 290 passed (backend untouched; confirms the version bump didn't break anything).
+
+- [ ] **Step 8: Commit**
+
+```bash
+git add backend/pyproject.toml backend/app/settings.py frontend/package.json frontend/src/app/page.tsx frontend/src/components/results-view.tsx README.md CHANGELOG.md PLAN.md docs/PROGRESS_LOG.md backend/uv.lock
+git commit -m "chore(v0.9.7): bump version + docs ritual (legal docs)"
+```
+
+- [ ] **Step 9: Push, PR, CI, merge, smoke (confirm before tag)**
+
+Push the branch, open a PR, wait for CI green, merge to `main`. Prod smoke: `curl …/health` → `version: 0.9.7`; load `/privacy` + `/terms` on prod. Then **pause for user confirmation** before `git tag v0.9.7 && git push origin v0.9.7`.
+
+---
+
+## Self-review notes
+
+- **Spec coverage:** content §5.1/§5.2 → Tasks 2–3; rendering §3 (TSX + LegalProse) → Tasks 1–3; footer §6.2/§7 → Task 1; docs/legal §3 → Task 4; tests §8 → Task 4; exit criteria §9 → Task 5. All covered.
+- **Placeholder scan:** none — full page prose and component code included.
+- **Type consistency:** `LegalProse({title,lastUpdated,children})` and `LegalSection({heading,children})` signatures are used identically in Tasks 2–3; `SiteFooter` exported (named) and imported as named in layout + test; pages default-exported and imported as default in the test.
+- **No backend/data change:** "your choices" references the existing `/me` delete; no new endpoint.
+- **Test count:** frontend 54 → 57 (+3). Backend unchanged at 290.
diff --git a/docs/superpowers/specs/2026-05-28-v0.9.7-legal-docs-design.md b/docs/superpowers/specs/2026-05-28-v0.9.7-legal-docs-design.md
new file mode 100644
index 0000000..6edb5be
--- /dev/null
+++ b/docs/superpowers/specs/2026-05-28-v0.9.7-legal-docs-design.md
@@ -0,0 +1,130 @@
+# v0.9.7 — Privacy policy + terms design spec
+
+**Status:** Designed. Implementation plan to follow under `docs/superpowers/plans/`.
+**Date:** 2026-05-28.
+**Author:** Claude (Opus 4.7) with Shaan.
+
+> **Not legal advice.** This spec defines lightweight, honest, plain-language legal pages grounded in the app's actual data practices. A professional should review them before relying on them for a public launch.
+
+---
+
+## 1. Goal
+
+Ship a Privacy Policy and Terms of Service as styled, indexable pages on the frontend, linked from a new global footer. Content is tailored to what Skill Issue actually does — no boilerplate that overpromises. This is the final pre-1.0 slice.
+
+## 2. Locked facts (2026-05-28)
+
+| Field | Value |
+| --- | --- |
+| Operator | Shaan Satsangi (individual) |
+| Contact | shaansatsangi.cse@gmail.com |
+| Governing law | India |
+| Minimum age | 13+ (matches GitHub) |
+| Tone | Lightweight, honest, plain-language |
+| Effective / "Last updated" | 2026-05-28 |
+
+## 3. Locked scope decisions (2026-05-28)
+
+| Decision | Choice | Why |
+| --- | --- | --- |
+| Format | **Static TSX pages** (`/privacy`, `/terms`), not markdown | No new dependency, full design control, single source of truth, SEO/PPR-friendly. |
+| Shared styling | A small **`LegalProse`** wrapper component | DRY the prose/heading styling across both pages. |
+| Footer | New global **`SiteFooter`** in the root layout | "Link from frontend footer" — none exists today. Minimal, subtle, responsive. |
+| `docs/legal/` | A short **`README.md` pointer** to the rendered pages | Satisfies PLAN's `docs/legal/` mention without a prose duplicate that would drift. |
+| Depth | Lightweight (no cookie-consent banner, no DSAR tooling, no GDPR/CCPA machinery) | The user's "lightweight, honest" choice; matches a solo pre-launch. |
+
+## 4. Operating context — what the app actually does with data
+
+Grounded in the codebase (so the Privacy content is truthful, not generic):
+- **GitHub OAuth `read:user`** (v0.9.5): on sign-in we read the user's public profile (login, name, avatar). The access token is **AES-GCM encrypted at rest** in the `sessions` table.
+- **Saved analyses + history** (`/me`): when signed in, analyses you run are persisted (Neon Postgres) until you delete them; deletion cascades runs + narratives.
+- **IP address** for rate limiting (v0.9.2): hashed/keyed per UTC-hour bucket in Upstash; not stored long-term.
+- **Caches** (Upstash): Report cache (~6 h TTL), GitHub-API cache, narrative cache — transient.
+- **AI narrative**: report data is sent to **Groq** (OpenAI-compatible) to generate the Roast/Mentor text.
+- **Analytics**: **PostHog** (events + web vitals); **Sentry** (error telemetry).
+- **Hosting**: **Vercel**; **database**: **Neon**.
+- **Cookies**: a session cookie (`si_session`, httpOnly, Secure, SameSite=Lax, ~30-day TTL) and a short-lived OAuth `state` cookie. No third-party advertising cookies.
+
+These map directly to the Privacy "what we collect / how we use it / subprocessors / retention" sections.
+
+## 5. Content outline
+
+### 5.1 Privacy Policy (`/privacy`)
+1. **Intro** — who operates the service (Shaan Satsangi), effective date, plain-language promise.
+2. **What we collect** — GitHub public profile (`read:user`); analyses you run + saved history (signed-in); IP address (rate limiting); product analytics + error telemetry; session cookie.
+3. **How we use it** — produce + display reports, persist your history, prevent abuse, improve reliability.
+4. **Third parties / subprocessors** — GitHub, Vercel, Neon, Upstash, Groq, Sentry, PostHog (each with a one-line purpose).
+5. **Retention** — sessions ~30 days; saved analyses until you delete them; caches transient.
+6. **Your choices** — delete saved analyses, sign out, revoke GitHub access (link to GitHub settings).
+7. **Cookies** — session + OAuth-state only; no ad cookies.
+8. **Children** — 13+.
+9. **Changes** — we may update; "last updated" reflects the date.
+10. **Contact** — shaansatsangi.cse@gmail.com.
+
+### 5.2 Terms of Service (`/terms`)
+1. **Acceptance** — using the service = agreeing.
+2. **What the service is** — opinionated, automated GitHub analysis for insight + entertainment; **explicitly not** an authoritative hiring, credit, or employment-decision tool; scores are subjective/automated and may be wrong.
+3. **Accounts** — optional GitHub OAuth sign-in; you're responsible for your GitHub account.
+4. **Acceptable use** — no abuse, automated scraping, circumventing rate limits, or attempting to disrupt the service.
+5. **Intellectual property** — the service + its scoring are ours; GitHub data belongs to its owners/GitHub.
+6. **Disclaimers** — provided "as is," no warranty, scores are subjective and automated.
+7. **Limitation of liability** — to the extent permitted by law, not liable for damages arising from use.
+8. **Termination** — we may suspend abusive use; you may stop + delete your data anytime.
+9. **Governing law** — India.
+10. **Changes** + **Contact** — shaansatsangi.cse@gmail.com.
+
+## 6. Surface area
+
+### 6.1 New files
+| File | Responsibility |
+| --- | --- |
+| `frontend/src/components/legal-prose.tsx` | `LegalProse` — presentational wrapper: page title, "Last updated" line, consistent prose/heading/link styling. Takes `title`, `lastUpdated`, `children`. |
+| `frontend/src/app/privacy/page.tsx` | Static server component; Privacy content (§5.1) inside `LegalProse`; page `metadata`. |
+| `frontend/src/app/terms/page.tsx` | Static server component; Terms content (§5.2) inside `LegalProse`; page `metadata`. |
+| `frontend/src/components/site-footer.tsx` | `SiteFooter` — global footer: `Privacy · Terms` + GitHub repo link; subtle, responsive. |
+| `frontend/src/components/__tests__/legal-pages.test.tsx` | Smoke tests: each page renders, shows its heading + the contact email; footer renders both links. |
+| `docs/legal/README.md` | Pointer to the rendered `/privacy` + `/terms` pages + last-updated note. |
+
+### 6.2 Modified files
+| File | Change |
+| --- | --- |
+| `frontend/src/app/layout.tsx` | Render `` inside `` after the children/providers so it sits at the bottom (body is already `min-h-full flex flex-col`). |
+| Version literals + CHANGELOG + PLAN + PROGRESS_LOG | Release ritual (0.9.6 → 0.9.7). |
+
+### 6.3 Untouched (intentionally)
+- Backend — no API or data-handling change; this slice is documentation + frontend presentation.
+- No new dependency (TSX, not markdown rendering).
+
+## 7. Footer + landing-layout consideration
+
+`layout.tsx` body is `min-h-full flex flex-col` with `` then content. Adding `` at the end keeps the footer at the bottom; the landing page's `flex-1` hero still centers in the remaining space. **Must verify** the full-height landing hero isn't visually disrupted and the footer reads well at mobile breakpoints (per the non-negotiable responsive rule). The footer is unobtrusive: small muted text, a thin top border, links to `/privacy`, `/terms`, and the GitHub repo.
+
+## 8. Tests
+
+Per the project norm (UI doesn't need 100% coverage — visual verification is fine), keep tests minimal:
+- `legal-pages.test.tsx`: render `Privacy` page → asserts the "Privacy" heading + contact email present; render `Terms` page → asserts "Terms" heading + governing-law mention; render `SiteFooter` → asserts links to `/privacy` and `/terms`.
+- Plus `next build` + a visual check of `/privacy`, `/terms`, and the footer on desktop + mobile.
+
+## 9. Exit criteria
+
+- [ ] `/privacy` and `/terms` render the §5 content via `LegalProse`, with page metadata and a "Last updated 2026-05-28" line.
+- [ ] Global `SiteFooter` links to both pages (+ GitHub) and is in the root layout; landing hero intact; mobile verified.
+- [ ] `docs/legal/README.md` points to the rendered pages.
+- [ ] `legal-pages.test.tsx` passes; frontend `lint` + `tsc` + `test:run` + `build` clean.
+- [ ] Docs ritual + version bump to 0.9.7; PLAN v0.9.7 row flipped ✅; tag `v0.9.7` + release.
+
+## 10. Out of scope
+- Cookie-consent banner / preference center.
+- DSAR (data-subject-access-request) tooling or a self-serve "download my data."
+- GDPR/CCPA-specific rights sections and a formal subprocessor agreement.
+- Backend changes (no new data collection or deletion endpoints — `/me` delete already exists and is referenced under "your choices").
+- A markdown-rendering pipeline.
+
+## 11. Implementation ordering
+1. `LegalProse` wrapper + `SiteFooter` component (+ wire footer into `layout.tsx`); verify landing hero + mobile.
+2. `/privacy` page (content + metadata).
+3. `/terms` page (content + metadata).
+4. `legal-pages.test.tsx` smoke tests + `docs/legal/README.md`.
+5. Docs ritual + version bump + ship (PR → CI → merge → prod smoke → confirm before tag).
+
+**Reversibility:** additive (new components/pages/footer); reverting removes the pages + footer with no data or backend impact.
diff --git a/frontend/package.json b/frontend/package.json
index a261c64..8d89e88 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,6 +1,6 @@
{
"name": "frontend",
- "version": "0.9.6",
+ "version": "0.9.7",
"private": true,
"scripts": {
"dev": "next dev",
diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx
index 55d4385..08f3dd3 100644
--- a/frontend/src/app/layout.tsx
+++ b/frontend/src/app/layout.tsx
@@ -1,6 +1,7 @@
import type { Metadata, Viewport } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { FramerProvider } from "@/components/framer-provider";
+import { SiteFooter } from "@/components/site-footer";
import { SiteHeader } from "@/components/site-header";
import { ObservabilityProvider } from "@/observability/provider";
import "./globals.css";
@@ -44,6 +45,7 @@ export default function RootLayout({
{children}
+
);
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx
index efe5837..efc3cee 100644
--- a/frontend/src/app/page.tsx
+++ b/frontend/src/app/page.tsx
@@ -23,7 +23,7 @@ export default function Home() {
transition={{ delay: 0.2, duration: 0.5 }}
className="rounded-full border border-white/10 bg-white/5 px-3 py-1 text-xs font-medium uppercase tracking-wider text-muted-foreground"
>
- Deterministic engineering reports · v0.9.6
+ Deterministic engineering reports · v0.9.7
diff --git a/frontend/src/app/privacy/page.tsx b/frontend/src/app/privacy/page.tsx
new file mode 100644
index 0000000..1290b94
--- /dev/null
+++ b/frontend/src/app/privacy/page.tsx
@@ -0,0 +1,137 @@
+import type { Metadata } from "next";
+import { LegalProse, LegalSection } from "@/components/legal-prose";
+
+export const metadata: Metadata = {
+ title: "Privacy Policy — Skill Issue",
+ description: "What Skill Issue collects, how it's used, and your choices.",
+};
+
+const EMAIL = "shaansatsangi.cse@gmail.com";
+
+export default function PrivacyPage() {
+ return (
+
+
+ Skill Issue is operated by Shaan Satsangi (“we”). This policy explains, in plain
+ language, what we collect, why, and the choices you have. We collect as little as we need to
+ run the service.
+
+
+
+
+
+ GitHub profile (if you sign in). We use
+ GitHub OAuth with read-only read:user scope to read your public profile
+ (login, name, avatar). Your GitHub access token is encrypted at rest.
+
+
+ Analyses and history. When signed in, the
+ analyses you run are saved to your history until you delete them.
+
+
+ IP address. Used transiently to rate-limit
+ requests and prevent abuse.
+
+
+ Usage and error data. Aggregate product
+ analytics and error reports help us keep the service working.
+
+
+ A session cookie. Keeps you signed in.
+
+
+
+
+
+
+ To generate and display your report, save your history when you’re signed in, prevent
+ abuse, and improve reliability. We do not sell your data or use it for advertising.
+
+
+
+
+
We rely on a few service providers to run Skill Issue:
+
+
+ GitHub — the source of the public data we
+ analyze.
+
+
+ Vercel — hosting.
+
+
+ Neon — database (accounts, saved analyses).
+
+
+ Upstash — short-lived caching and
+ rate-limit counters.
+
+
+ Groq — generates the AI narrative from your
+ report.
+
+
+ Sentry — error monitoring.
+
+
+ PostHog — product analytics.
+
+
+
+
+
+
+ Sign-in sessions expire after about 30 days. Saved analyses stay until you delete them.
+ Caches are short-lived and expire automatically.
+
+
+
+
+
+ You can delete saved analyses from your history, sign out at any time, and revoke
+ Skill Issue’s access from your{" "}
+
+ GitHub application settings
+
+ .
+
+
+
+
+
+ We use a session cookie to keep you signed in and a short-lived cookie during the GitHub
+ sign-in flow. We do not use advertising or cross-site tracking cookies.
+
+
+
+
+
Skill Issue is intended for users aged 13 and older, consistent with GitHub.
+
+
+
+
+ We may update this policy; the “last updated” date above reflects the latest
+ version.
+
+
+
+ );
+}
diff --git a/frontend/src/app/terms/page.tsx b/frontend/src/app/terms/page.tsx
new file mode 100644
index 0000000..9a42126
--- /dev/null
+++ b/frontend/src/app/terms/page.tsx
@@ -0,0 +1,100 @@
+import type { Metadata } from "next";
+import { LegalProse, LegalSection } from "@/components/legal-prose";
+
+export const metadata: Metadata = {
+ title: "Terms of Service — Skill Issue",
+ description: "The terms for using Skill Issue.",
+};
+
+const EMAIL = "shaansatsangi.cse@gmail.com";
+
+export default function TermsPage() {
+ return (
+
+
+ By using Skill Issue (operated by Shaan Satsangi), you agree to these terms. If you
+ don’t agree, please don’t use the service.
+
+
+
+
+ Skill Issue produces an opinionated, automated analysis of a public GitHub profile for
+ insight and entertainment. The scores and commentary are generated by software and may be
+ incomplete or wrong. Skill Issue is not an
+ authoritative hiring, credit, employment, or background-check tool, and should not be used
+ to make decisions about people.
+
+
+
+
+
+ Signing in is optional and uses GitHub OAuth. You are responsible for activity under your
+ GitHub account and for keeping it secure.
+
+
+
+
+
You agree not to:
+
+
abuse, overload, or attempt to disrupt the service;
+
scrape it or access it through automated means outside normal use;
+
circumvent rate limits or security measures;
+
use it to harass others or for unlawful purposes.
+
+
+
+
+
+ The service, its design, and its scoring system belong to us. GitHub data shown in a report
+ belongs to its respective owners and GitHub; we present it for analysis.
+
+
+
+
+
+ The service is provided “as is” and “as available,” without
+ warranties of any kind. Scores are subjective, automated estimates and are not guarantees
+ of skill, quality, or fitness for any purpose.
+
+
+
+
+
+ To the maximum extent permitted by law, we are not liable for any indirect, incidental, or
+ consequential damages arising from your use of the service.
+
+
+
+
+
+ We may suspend or limit access that abuses the service. You can stop using it and delete
+ your saved data at any time.
+
+
+
+
+
These terms are governed by the laws of India.
+
+
+
+
+ We may update these terms; the “last updated” date above reflects the latest
+ version. Continued use means you accept the changes.
+