feat(confidence-engine): add tester legal pages
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import React from "react";
|
||||
import LegalPageLayout from "@/components/legal-page-layout";
|
||||
|
||||
export default function CookiesPage() {
|
||||
return (
|
||||
<LegalPageLayout title="Cookie Policy">
|
||||
<p>This policy explains the browser storage Confidence Engine currently uses. LocalStorage and sessionStorage are browser storage technologies; they are not necessarily HTTP cookies.</p>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Authentication and session cookies</h2>
|
||||
<p>Confidence Engine uses Supabase authentication and session cookies to provide secure sign-in and keep authenticated users signed in. These are essential to the authenticated service. Runtime cookie names and durations are managed by the authentication system.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Theme preference</h2>
|
||||
<p><strong>confidence-engine-theme</strong> is stored in localStorage to remember your light or dark display preference. It remains until you change the preference or clear browser storage.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Introductory guidance preference</h2>
|
||||
<p><strong>ce-facilitator-dismissed</strong> is stored in sessionStorage if you dismiss introductory guidance. It is session-scoped and remembers that choice while the browser session remains available.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">No analytics or advertising tracking</h2>
|
||||
<p>Confidence Engine currently does not use advertising cookies, analytics cookies, tracking pixels, marketing cookies, or third-party browser tracking based on the current implementation.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Future changes</h2>
|
||||
<p>If Confidence Engine later introduces non-essential cookies or similar technologies, this policy and any consent mechanism will be reconsidered as appropriate.</p>
|
||||
</section>
|
||||
</LegalPageLayout>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import "./globals.css";
|
||||
import ThemeToggle from "@/components/theme-toggle";
|
||||
import LogoutButton from "@/components/logout-button";
|
||||
import LegalNavigation from "@/components/legal-navigation";
|
||||
|
||||
export const metadata = {
|
||||
title: "Confidence Engine",
|
||||
@@ -26,6 +27,9 @@ export default function RootLayout({ children }) {
|
||||
</div>
|
||||
</header>
|
||||
{children}
|
||||
<footer className="app-chrome border-t border-gray-200/80 px-6 py-5">
|
||||
<LegalNavigation />
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import React from "react";
|
||||
import LegalPageLayout from "@/components/legal-page-layout";
|
||||
|
||||
export default function PrivacyPage() {
|
||||
return (
|
||||
<LegalPageLayout title="Privacy Policy">
|
||||
<p>This policy explains how Confidence Engine handles information when you use the service.</p>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Who is responsible</h2>
|
||||
<p>Confidence Engine is operated by RDB Solutions Ltd., Palmeira Avenue Mansions, 19 Church Road, Hove, East Sussex, England, BN3 2FA. For privacy questions or deletion requests, contact <a className="text-teal-700 underline" href="mailto:data@rdbtech.co.uk">data@rdbtech.co.uk</a>.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Information we process</h2>
|
||||
<p>We process your account email and authentication information, together with information you choose to enter into an investigation. This can include scenario descriptions, reconstructed SituationGraph material, Current Understanding, Open Questions, answers, Findings, Contributions, reports, and revision and timestamp metadata.</p>
|
||||
<p>Please do not enter personal information that you do not need to provide, especially unnecessary information about other people.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Why we use it</h2>
|
||||
<p>We use account information to provide secure access to your account. We use investigation information to save your work, let you return to it, and provide the reasoning features you request. Confidence Engine supports your understanding; it does not make decisions for you.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Storage and reasoning</h2>
|
||||
<p>Authentication and investigation persistence are operated through our self-hosted Supabase and PostgreSQL infrastructure. Reasoning requests are processed through private Ollama/Qwen infrastructure used by the service. We also use functional browser storage for authentication sessions and interface preferences; see our Cookie Policy for details.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Retention and deletion</h2>
|
||||
<p>Account and investigation information is retained while your account remains active. After 18 months without activity, we will contact you before deletion; if inactivity continues, account and investigation information may then be automatically deleted. You may request deletion at <a className="text-teal-700 underline" href="mailto:data@rdbtech.co.uk">data@rdbtech.co.uk</a>.</p>
|
||||
<p>Deleted information may remain temporarily in rotating backups until those backups expire.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Security and your rights</h2>
|
||||
<p>We use access controls and technical measures appropriate to operating the service. You can contact us about access, correction, deletion, or other data-protection requests. You may also complain to the UK Information Commissioner's Office.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Age and changes</h2>
|
||||
<p>Confidence Engine is for people aged 18 and over. We may update this policy as the service develops; the current version will be published on this page.</p>
|
||||
</section>
|
||||
</LegalPageLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import React from "react";
|
||||
import LegalPageLayout from "@/components/legal-page-layout";
|
||||
|
||||
export default function TermsPage() {
|
||||
return (
|
||||
<LegalPageLayout title="Terms of Use">
|
||||
<p>Confidence Engine is operated by RDB Solutions Ltd. These Terms govern your use of the service.</p>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Eligibility and accounts</h2>
|
||||
<p>You must be at least 18 years old to use Confidence Engine. Keep access to your email account and sign-in link secure, and provide accurate information when creating or using an account.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Using the service</h2>
|
||||
<p>Use the service lawfully and responsibly. You are responsible for the information you enter and should avoid entering information about others unless it is necessary and appropriate to do so.</p>
|
||||
<p>Confidence Engine facilitates understanding; it does not make decisions for you. AI or model-generated analysis may be incomplete, inaccurate, or unsuitable for your circumstances. It is not professional, legal, financial, medical, or other regulated advice. You remain responsible for your decisions and actions.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Availability</h2>
|
||||
<p>We aim to keep the service available, but availability may vary. Reasoning functionality may occasionally be temporarily unavailable, and we may change, suspend, or withdraw parts of the service when reasonably necessary.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Your information and intellectual property</h2>
|
||||
<p>You retain responsibility for your underlying scenarios and information. We do not claim ownership of that underlying material merely because you use the service. The Confidence Engine service, branding, and software remain the property of RDB Solutions Ltd. or its licensors.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Ending access and liability</h2>
|
||||
<p>You may stop using the service and request account deletion at <a className="text-teal-700 underline" href="mailto:data@rdbtech.co.uk">data@rdbtech.co.uk</a>. We may suspend or end access where reasonably necessary, including for misuse or security reasons.</p>
|
||||
<p>Nothing in these Terms excludes liability that cannot legally be excluded. Subject to that, the service is provided for a controlled early release and we are not liable for indirect loss or for decisions you make using it.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-xl font-semibold text-gray-900">Changes and law</h2>
|
||||
<p>We may update these Terms by publishing the revised version on this page. These Terms are governed by the law of England and Wales. Questions can be sent to <a className="text-teal-700 underline" href="mailto:data@rdbtech.co.uk">data@rdbtech.co.uk</a>.</p>
|
||||
</section>
|
||||
</LegalPageLayout>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function LegalNavigation() {
|
||||
return (
|
||||
<nav aria-label="Legal information" className="flex flex-wrap justify-center gap-x-5 gap-y-2 text-sm text-gray-500">
|
||||
<Link href="/privacy" className="hover:text-teal-700">Privacy</Link>
|
||||
<Link href="/terms" className="hover:text-teal-700">Terms</Link>
|
||||
<Link href="/cookies" className="hover:text-teal-700">Cookies</Link>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
import LegalNavigation from "@/components/legal-navigation";
|
||||
|
||||
export default function LegalPageLayout({ title, children }) {
|
||||
return (
|
||||
<main className="mx-auto min-h-[calc(100vh-57px)] max-w-3xl px-6 py-12 sm:py-16">
|
||||
<Link href="/login" className="text-sm font-medium text-teal-700 hover:underline">
|
||||
Back to sign in
|
||||
</Link>
|
||||
<article className="mt-6 rounded-xl border-[2.5px] border-teal-300/70 bg-gradient-to-b from-teal-50/60 to-white px-6 py-8 shadow-sm sm:px-10">
|
||||
<h1 className="text-3xl font-bold tracking-tight text-teal-700">{title}</h1>
|
||||
<div className="mt-8 space-y-7 text-base leading-relaxed text-gray-700">
|
||||
{children}
|
||||
</div>
|
||||
</article>
|
||||
<footer className="mt-8 border-t border-gray-200 pt-5">
|
||||
<LegalNavigation />
|
||||
</footer>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,12 @@
|
||||
> **Role:** Concise operational snapshot for resuming work today. Not a historical diary.
|
||||
> The design evolution archive index at `docs/design-evolution/README.md` provides progressive loading of experiment history; load the relevant chapter only when a specific historical question requires it.
|
||||
|
||||
## Tester legal information
|
||||
|
||||
- Public Privacy, Terms, and Cookie pages and shared legal navigation are available at `/privacy`, `/terms`, and `/cookies`.
|
||||
- The service is positioned as 18+. No cookie-consent banner is used because current browser storage is limited to essential authentication/session storage and functional UI preferences.
|
||||
- Legal wording remains subject to appropriate professional review.
|
||||
|
||||
## Focused-investigation provider outage boundary
|
||||
|
||||
- Focused-investigation outage handling now sanitizes provider failure at the API boundary: unavailable focused reasoning returns a controlled HTTP 503, and raw provider/Ollama diagnostics no longer leave that boundary.
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# Current Project State — Confidence Engine
|
||||
|
||||
## Tester Legal Information
|
||||
|
||||
- Public Privacy, Terms, and Cookie pages and shared legal navigation are available at `/privacy`, `/terms`, and `/cookies`.
|
||||
- The service is positioned as 18+. No cookie-consent banner is used because current browser storage is limited to essential authentication/session storage and functional UI preferences.
|
||||
- Legal wording remains subject to appropriate professional review.
|
||||
|
||||
## Focused-Investigation Provider Outage Boundary
|
||||
|
||||
- Focused-investigation outage handling now sanitizes provider failure at the API boundary: unavailable focused reasoning returns a controlled HTTP 503, and raw provider/Ollama diagnostics no longer leave that boundary.
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { createServerClient } from "@supabase/ssr";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
const PUBLIC_PATHS = ["/login", "/auth", "/api/health"];
|
||||
const PUBLIC_PATHS = ["/login", "/auth", "/api/health", "/privacy", "/terms", "/cookies"];
|
||||
|
||||
export async function middleware(request) {
|
||||
const pathname = request.nextUrl.pathname;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import React from "react";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
import { NextRequest } from "next/server";
|
||||
import PrivacyPage from "@/app/privacy/page.jsx";
|
||||
import TermsPage from "@/app/terms/page.jsx";
|
||||
import CookiesPage from "@/app/cookies/page.jsx";
|
||||
import LegalNavigation from "@/components/legal-navigation.jsx";
|
||||
import { middleware } from "@/middleware.js";
|
||||
|
||||
describe("public legal pages", () => {
|
||||
it.each([
|
||||
["Privacy Policy", PrivacyPage],
|
||||
["Terms of Use", TermsPage],
|
||||
["Cookie Policy", CookiesPage],
|
||||
])("renders the %s heading", (heading, Page) => {
|
||||
const html = renderToStaticMarkup(<Page />);
|
||||
expect(html).toContain(`<h1 class="text-3xl font-bold tracking-tight text-teal-700">${heading}</h1>`);
|
||||
});
|
||||
|
||||
it("exposes all public legal links without cookie consent controls", () => {
|
||||
const html = renderToStaticMarkup(<LegalNavigation />);
|
||||
expect(html).toContain('href="/privacy"');
|
||||
expect(html).toContain('href="/terms"');
|
||||
expect(html).toContain('href="/cookies"');
|
||||
expect(html).not.toMatch(/Accept cookies|Reject cookies/i);
|
||||
});
|
||||
|
||||
it.each(["privacy", "terms", "cookies"])("keeps /%s public", async (path) => {
|
||||
const response = await middleware(new NextRequest(`http://localhost:3000/${path}`));
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user