# Source-Grounded Proof API Route Protection Readiness V01

Issue: [#182](https://github.com/pinklon/ai-capability-discipline/issues/182)

Upstream decision: [#188](https://github.com/pinklon/ai-capability-discipline/issues/188)

Date: 2026-06-30

Repository: `pinklon/ai-capability-discipline`

Baseline commit: `04782b6a1df846cf85a167dbfe4cc332337bffc3`

## Purpose And Implementation Boundary

This packet implements the repo-local readiness layer for the hybrid Ghostmesh access posture selected by #188.

It records the route inventory, public and protected surface split, navigation posture, protected proof and API route set, redirect and fallback-domain expectations, Cloudflare Access and rate-limit runbook status, unauthenticated and authenticated smoke expectations, validation coverage, and residual risks for #182.

This is a repository documentation, validation, and receipt artifact. It does not change Cloudflare configuration, provider/model configuration, runtime retrieval behavior, source registries, approved source sets, package authority, uploaded/session-source behavior, external/current context mode, company-specific content, client-side authentication, shared passwords, vector databases, Supabase, hosted retrieval, knowledge graphs, Cloudflare Pages hosting, GitHub source-of-truth posture, #269, #271, issue labels, or `codex-automerge`.

## Route Inventory

| Route or surface | Expected posture | Validation expectation | Notes |
|---|---|---|---|
| `https://ghostmesh.ai/` | Public | Unauthenticated `200` or equivalent successful public load. | Canonical public landing and reader orientation surface. |
| `https://www.ghostmesh.ai/` | Redirect to apex | Redirect must land on `https://ghostmesh.ai/`. | `www` is not the proof authority. |
| `https://ghostmesh.ai/html/*` | Public | Approved artifact pages load unauthenticated. | Public package reading surface. |
| `https://ghostmesh.ai/downloads/*` | Public | Approved downloads remain reachable unauthenticated. | Only already approved public exports belong here. |
| `https://ghostmesh.ai/context-pack/*` | Public while approved package material only | Public context-pack mirrors load and hashes validate. | Revisit before private, company-specific, uploaded, or less-public sources enter any published mirror. |
| `https://ghostmesh.ai/artifact-manifest.json` | Public | Manifest loads unauthenticated. | Public package identity and hash evidence. |
| `https://ghostmesh.ai/source-grounded-chat-proof*` | Protected | Unauthenticated request requires Access or equivalent protection. | Provider-backed proof surface. |
| `https://ghostmesh.ai/source-grounded-chat-proof-runbook.md` | Protected in production contract mode | Unauthenticated request requires Access or equivalent protection when Cloudflare-required production smoke is used. | The runbook exposes proof operation details and follows the protected proof route family. |
| `https://ghostmesh.ai/api/source-grounded-chat*` | Protected | Unauthenticated request requires Access, controlled denial, or method-limited response with no provider execution. | Provider/API boundary. |
| Cloudflare preview aliases with provider-backed smoke | Protected or explicitly allowlisted | Provider-backed smoke must use an approved protected or allowlisted origin. | Random PR preview URLs are not provider-enabled by default. |
| Immutable Cloudflare deploy URLs with provider-backed smoke | Protected or unapproved for provider-backed smoke | Treat as unapproved unless explicitly protected and allowlisted. | Prevents bypass around the canonical protected path. |
| GitHub Pages fallback or historical mirrors | Public fallback only | Must not bypass protected proof/API behavior. | Fallback can serve approved static package material, not provider-backed execution. |
| Future company-specific content | Protected by default | No public publication without a separate owner-approved release decision and validation receipt. | Not implemented here. |
| Future uploaded/session-source behavior | Protected by default | No runtime or corpus ingestion without a separate owner-approved implementation. | Not implemented here. |
| Future external/current context mode with private or provider-backed inputs | Protected by default | Keep source authorization, Access-authenticated smoke, and rollback evidence before expansion. | Not implemented here. |

## Public Surface Matrix

Public surfaces remain limited to approved package and reader material:

- public landing page
- approved published artifact pages
- approved public downloads and portable HTML exports
- artifact manifest and hash evidence
- public `context-pack` mirrors while they contain approved public package material only
- architecture notes and receipts that are public-safe and do not expose account, token, session, provider, or private-source details

Public surfaces must not include company-specific content, uploaded/session-source material, raw private enrichment sources, raw protected smoke telemetry, provider credentials, Cloudflare credentials, cookies, service tokens, raw request headers, raw response headers, secret-bearing redirect URLs, or broad public provider-backed endpoint exposure.

## Protected Surface Matrix

Protected surfaces are:

- `https://ghostmesh.ai/source-grounded-chat-proof*`
- `https://ghostmesh.ai/source-grounded-chat-proof-runbook.md` when the production contract requires protected proof documentation
- `https://ghostmesh.ai/api/source-grounded-chat*`
- provider-backed preview aliases used for smoke
- immutable deploy URLs used for provider-backed smoke
- future private artifacts
- future company-specific content
- future uploaded/session-source workflows
- future external/current context lanes that use live retrieval, provider execution, private inputs, or less-public source sets

Protection is route-scoped. The public package site must not become private as a side effect of protecting proof and API paths.

## Public And Protected Navigation Split

Primary public navigation should continue to lead readers to:

- Playbook Home
- Playbook Map
- Shared Foundations
- AI Capability Discipline
- Architecture Notes
- approved public artifact pages and downloads

Assistant/proof navigation can remain visible as a public route label, but production access to the proof page must be protected by Cloudflare Access or an equivalent external access control. Public UI text must not imply enterprise approval, provider approval, production approval, company-policy approval, or broad public availability of provider-backed execution.

Future private lanes should be labeled as Access-required or private before implementation. They must not reuse public package navigation in a way that suggests private content is part of the approved public corpus.

## Cloudflare Access Status And Runbook

Cloudflare Access is external account configuration, not repository state. This repository must not contain API tokens, provider keys, Access service tokens, shared passwords, `.env`, `.dev.vars`, `wrangler.toml`, secret-bearing screenshots, or secret-bearing logs.

Current target Access route set:

```text
https://ghostmesh.ai/source-grounded-chat-proof*
https://ghostmesh.ai/source-grounded-chat-proof-runbook.md
https://ghostmesh.ai/api/source-grounded-chat*
```

Expected Access policy shape:

- allow `tony@crysco.com`
- allow `malott@gmail.com` only while it remains an explicitly approved reviewer identity
- allow other trusted reviewers only when explicitly named by the owner
- deny everyone else
- no shared password in static HTML or JavaScript
- no client-side-only gate

Manual dashboard or API verification steps:

1. Confirm the Cloudflare Access application covers the proof page route and API route.
2. Confirm the application path rules include the production apex host.
3. Confirm `www` is covered only if it can serve proof/API paths instead of redirecting to apex.
4. Confirm the policy allows only the owner-approved identities.
5. Confirm unauthenticated proof and API requests return a Cloudflare Access challenge, redirect, `401`, `403`, controlled denial, or method-limited response without provider execution.
6. Confirm authenticated browser smoke reaches the proof page, calls `/api/source-grounded-chat` only after approved refs exist, and records zero direct browser provider requests.
7. Confirm unsupported prompts select `0` approved refs and make `0` provider/API calls where existing proof behavior supports that check.

## Rate-Limit And Abuse-Control Posture

The Pages Function already applies defense-in-depth controls for method handling, allowed origins, request body size, selected source count, snippet size, public path allowlisting, deterministic refusal, best-effort per-isolate request buckets, and sanitized errors.

Durable abuse control belongs at the Cloudflare edge. The currently validated WAF shape from the earlier rate-limit lane is:

```text
Host: ghostmesh.ai
Method: POST
Path: /api/source-grounded-chat*
Action: block
Limit: 5 requests per 10 seconds
Mitigation timeout: 10 seconds
Counting characteristics: cf.colo.id and ip.src
```

If Cloudflare plan entitlements or dashboard fields change, use the narrowest supported equivalent for `POST /api/source-grounded-chat*` and record the exact limitation in the validation receipt. Do not rate-limit the public landing page, approved artifact pages, downloads, portable HTML exports, or public context-pack mirrors under this proof-specific rule.

## Smoke Expectations

Unauthenticated smoke:

- public landing page loads
- public approved artifacts load
- public approved corpus decision is respected
- public context-pack mirrors remain reachable while they contain approved public package material only
- proof page requires protection or records a pending protection gap
- `/api/source-grounded-chat` requires protection, returns controlled denial, or returns method-limited response without provider execution
- fallback domains do not bypass protected proof/API routes

Authenticated or protected-path smoke, when an approved Access session is available:

- proof page loads only through the approved access path
- positive query uses approved refs
- `/api/source-grounded-chat` is called through the server boundary
- direct browser provider request count remains `0`
- unsupported query selects `0` refs and makes `0` provider/API calls where the existing proof behavior supports that check
- provider/API errors are sanitized
- current/public citations remain enrichment only and do not become package authority

If authenticated smoke is unavailable, record the exact blocker and keep the PR draft.

## Validation Coverage

This readiness packet is validated by:

```bash
python3 -B scripts/build_context_pack.py
python3 -B validation/scripts/check_source_grounded_proof_api_route_protection_readiness.py
python3 -B validation/scripts/check_context_pack.py
python3 -B validation/scripts/check_minimal_external_chat_proof.py
python3 -B validation/scripts/check_published_site_contract.py
python3 -B validation/scripts/run_all.py
git diff --check
```

If `check_published_site_contract.py` or `run_all.py` fails only because the local static server cannot bind in the sandbox, rerun through the established local-server privilege path and record both the initial failure and the privileged rerun result.

Live Cloudflare validation should use only sanitized route/status evidence. Do not print cookies, OTP links, service tokens, provider keys, Cloudflare tokens, raw request headers, raw response headers, secret-bearing redirect URLs, or provider payloads.

## Residual Risks

- Cloudflare Access and WAF state live outside the repository, so repo validation can lock expected posture but cannot prove dashboard state without live smoke evidence.
- Public context-pack mirrors are appropriate only while they contain approved public package material.
- Random preview URLs can bypass expectations if they are provider-enabled without the protected or allowlisted origin discipline.
- Future uploaded/session-source and external/current context behavior need separate implementation gates before any private or less-public source material is introduced.
- Fallback domains must be checked after any deployment or DNS change so they do not expose protected proof/API paths.

## Explicit Boundary Confirmation

This packet does not make the whole public static site private.

This packet does not publish company-specific content.

This packet does not implement uploaded/session-source behavior.

This packet does not implement external/current context mode.

This packet does not change provider/model configuration.

This packet does not weaken grounding/refusal behavior.

This packet does not allow model answers without approved refs.

This packet does not expose provider secrets.

This packet does not add client-side-only password protection.

This packet does not put shared passwords in JavaScript or HTML.

This packet does not add an external vector DB, Supabase, hosted retrieval, or knowledge graph.

This packet does not move off Cloudflare Pages.

This packet does not abandon GitHub as source of truth.

This packet does not relabel issues.

This packet does not reopen #269 or #271.

This packet does not apply `codex-automerge`.
